[geocode-glib] tests: Port test-gcglib to optionally use GeocodeNominatim offline



commit 65dc1831d1ec775175590e15c90f0527847d04cc
Author: Philip Withnall <philip withnall collabora co uk>
Date:   Thu Oct 13 11:49:07 2016 +0100

    tests: Port test-gcglib to optionally use GeocodeNominatim offline
    
    GeocodeNominatim allows us to override its virtual methods for network
    queries, so do that in a new GeocodeNominatimTest subclass, which loads
    its results from a local set of results added by the test harness.
    
    Port the existing test-gcglib tests to optionally use this new backend,
    rather than the default GNOME Nominatim backend, to run the tests
    offline. This means that they can reliably be run on CI or build
    infrastructure with no internet access; and can be run with internet
    access on developer machines (for example).
    
    Based on a patch by Aleksander Morgado
    <aleksander morgado collabora co uk>.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=756311

 configure.ac                                |    2 +-
 docs/Makefile.am                            |    6 +-
 geocode-glib/Makefile.am                    |   27 +++-
 geocode-glib/test-gcglib.c                  |  260 ++++++++++++++++++++++++---
 geocode-glib/tests/geocode-nominatim-test.c |  249 +++++++++++++++++++++++++
 geocode-glib/tests/geocode-nominatim-test.h |   44 +++++
 geocode-glib/tests/locale_format.json       |    1 +
 geocode-glib/tests/locale_name.json         |    1 +
 geocode-glib/tests/osm_type0.json           |    1 +
 geocode-glib/tests/osm_type1.json           |    1 +
 geocode-glib/tests/osm_type2.json           |    1 +
 geocode-glib/tests/pub.json                 |    1 +
 geocode-glib/tests/rev.json                 |    1 +
 geocode-glib/tests/rev_fail.json            |    1 +
 geocode-glib/tests/search.json              |    1 +
 geocode-glib/tests/search_lat_long.json     |    1 +
 geocode-glib/tests/xep.json                 |    1 +
 17 files changed, 568 insertions(+), 31 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 32ab639..664e597 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,7 @@ AC_CONFIG_SRCDIR([geocode-glib/test-gcglib.c])
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([m4])
 
-AM_INIT_AUTOMAKE([1.11 dist-xz no-dist-gzip check-news])
+AM_INIT_AUTOMAKE([1.11 dist-xz no-dist-gzip check-news subdir-objects])
 
 # Before making a release, the GCLIB_LT_VERSION string should be modified.
 # The string is of the form C:R:A.
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 449f901..fc28e8b 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -52,8 +52,10 @@ CFILE_GLOB=$(top_srcdir)/geocode-glib/geocode-*.c
 
 # Header files to ignore when scanning.
 # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
-IGNORE_HFILES=                                 \
-       geocode-glib-private.h
+IGNORE_HFILES = \
+       geocode-glib-private.h \
+       geocode-nominatim-test.h \
+       $(NULL)
 
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/geocode-glib/Makefile.am b/geocode-glib/Makefile.am
index df5852b..03db567 100644
--- a/geocode-glib/Makefile.am
+++ b/geocode-glib/Makefile.am
@@ -108,12 +108,35 @@ CLEANFILES += $(gir_DATA) $(typelib_DATA)
 
 endif # HAVE_INTROSPECTION
 
-TEST_PROGS += test-geouri test-gcglib
-noinst_PROGRAMS = $(TEST_PROGS)
+TESTS = test-geouri test-gcglib
+noinst_PROGRAMS = $(TESTS)
+
+TESTS_ENVIRONMENT = \
+       G_TEST_SRCDIR="$(abs_srcdir)" \
+       G_TEST_BUILDDIR="$(abs_builddir)"
+
+test_gcglib_SOURCES = \
+       tests/geocode-nominatim-test.h \
+       tests/geocode-nominatim-test.c \
+       test-gcglib.c
 
 test_geouri_LDADD = libgeocode-glib.la $(GEOCODE_LIBS)
 test_gcglib_LDADD = libgeocode-glib.la $(GEOCODE_LIBS)
 
+EXTRA_DIST += \
+       tests/locale_format.json \
+       tests/locale_name.json \
+       tests/osm_type0.json \
+       tests/osm_type1.json \
+       tests/osm_type2.json \
+       tests/pub.json \
+       tests/rev.json \
+       tests/rev_fail.json \
+       tests/search.json \
+       tests/search_lat_long.json \
+       tests/xep.json \
+       $(NULL)
+
 MAINTAINERCLEANFILES = Makefile.in
 
 EXTRA_DIST +=                                   \
diff --git a/geocode-glib/test-gcglib.c b/geocode-glib/test-gcglib.c
index 16a72c5..c15e190 100644
--- a/geocode-glib/test-gcglib.c
+++ b/geocode-glib/test-gcglib.c
@@ -7,9 +7,10 @@
 #include <gio/gio.h>
 #include <geocode-glib/geocode-glib.h>
 #include <geocode-glib/geocode-glib-private.h>
+#include <geocode-glib/tests/geocode-nominatim-test.h>
 
 static GMainLoop *loop = NULL;
-
+static gboolean enable_network = FALSE;
 static char **params = NULL;
 
 static void
@@ -104,6 +105,156 @@ bbox_includes_location (GeocodeBoundingBox *bbox,
 }
 
 static void
+add_attr (GHashTable *ht,
+         const char *key,
+         const char *s)
+{
+       GValue *value;
+       value = g_new0 (GValue, 1);
+       g_value_init (value, G_TYPE_STRING);
+       g_value_set_static_string (value, s);
+       g_hash_table_insert (ht, g_strdup (key), value);
+}
+
+static void
+free_attr (GValue *attr)
+{
+       g_value_unset (attr);
+       g_free (attr);
+}
+
+static void
+add_attr_string (GHashTable  *ht,
+                 const gchar *key,
+                 const gchar *value)
+{
+       g_hash_table_insert (ht, (gpointer) key, (gpointer) value);
+}
+
+static gchar *
+load_json (const gchar *expected_response_filename)
+{
+       g_autofree gchar *expected_response = NULL;
+       g_autofree gchar *expected_response_path = NULL;
+       g_autoptr (GError) error = NULL;
+
+       expected_response_path = g_test_build_filename (G_TEST_DIST, "tests",
+                                                       expected_response_filename,
+                                                       NULL);
+       g_file_get_contents (expected_response_path, &expected_response, NULL,
+                            &error);
+       g_assert_no_error (error);
+
+       return g_steal_pointer (&expected_response);
+}
+
+static GeocodeReverse *
+create_reverse (GeocodeLocation *loc,
+                const gchar     *expected_response_filename)
+{
+       g_autoptr (GHashTable) parameters = NULL;
+       g_autoptr (GeocodeReverse) reverse = NULL;
+       char lat[G_ASCII_DTOSTR_BUF_SIZE];
+       char lon[G_ASCII_DTOSTR_BUF_SIZE];
+
+       /* Build the query parameters. */
+       g_ascii_dtostr (lat,
+                       G_ASCII_DTOSTR_BUF_SIZE,
+                       geocode_location_get_latitude (loc));
+       g_ascii_dtostr (lon,
+                       G_ASCII_DTOSTR_BUF_SIZE,
+                       geocode_location_get_longitude (loc));
+
+       parameters = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+                                           g_free);
+       add_attr_string (parameters, "lat", g_strdup (lat));
+       add_attr_string (parameters, "lon", g_strdup (lon));
+
+       reverse = geocode_reverse_new_for_location (loc);
+
+       if (!enable_network) {
+               g_autoptr (GeocodeNominatim) backend = NULL;
+               g_autofree gchar *expected_response = NULL;
+
+               /* Load the JSON we expect as a response. */
+               expected_response = load_json (expected_response_filename);
+
+               /* Build the backend and query object. */
+               backend = geocode_nominatim_test_new ();
+               geocode_nominatim_test_expect_query (GEOCODE_NOMINATIM_TEST (backend),
+                                                    parameters, expected_response);
+
+               geocode_reverse_set_backend (reverse, GEOCODE_BACKEND (backend));
+       }
+
+       return g_steal_pointer (&reverse);
+}
+
+/*
+ * @tp: (element-type utf8 GValue) (transfer none):
+ * @params: (element-type utf8 utf8) (transfer none):
+ * @expected_response_filename:
+ *
+ * Returns: (transfer full):
+ */
+static GeocodeForward *
+create_forward_for_params (GHashTable  *tp,
+                           GHashTable  *params,
+                           const gchar *expected_response_filename)
+{
+       g_autoptr (GeocodeForward) forward = NULL;
+
+       forward = geocode_forward_new_for_params (tp);
+
+       if (!enable_network) {
+               g_autoptr (GeocodeNominatim) backend = NULL;
+               g_autofree gchar *expected_response = NULL;
+
+               expected_response = load_json (expected_response_filename);
+
+               backend = geocode_nominatim_test_new ();
+               geocode_nominatim_test_expect_query (GEOCODE_NOMINATIM_TEST (backend),
+                                                    params, expected_response);
+
+               geocode_forward_set_backend (forward, GEOCODE_BACKEND (backend));
+       }
+
+       return g_steal_pointer (&forward);
+}
+
+/*
+ * @q:
+ * @params: (element-type utf8 utf8) (transfer none):
+ * @expected_response_filename:
+ *
+ * Returns: (transfer full):
+ */
+static GeocodeForward *
+create_forward_for_string (const gchar *q,
+                           GHashTable  *params,
+                           const gchar *expected_response_filename)
+{
+       g_autoptr (GeocodeForward) forward = NULL;
+
+       forward = geocode_forward_new_for_string (q);
+
+       if (!enable_network) {
+               g_autoptr (GeocodeNominatim) backend = NULL;
+               g_autofree gchar *expected_response = NULL;
+
+               expected_response = load_json (expected_response_filename);
+
+               backend = geocode_nominatim_test_new ();
+               geocode_nominatim_test_expect_query (GEOCODE_NOMINATIM_TEST (backend),
+                                                    params, expected_response);
+
+               geocode_forward_set_backend (forward, GEOCODE_BACKEND (backend));
+       }
+
+       return g_steal_pointer (&forward);
+}
+
+static void
 test_rev (void)
 {
        GeocodeLocation *loc;
@@ -112,7 +263,7 @@ test_rev (void)
        GeocodePlace *place;
 
        loc = geocode_location_new (51.2370361, -0.5894834, GEOCODE_LOCATION_ACCURACY_UNKNOWN);
-       rev = geocode_reverse_new_for_location (loc);
+       rev = create_reverse (loc, "rev.json");
        g_object_unref (loc);
 
        place = geocode_reverse_resolve (rev, &error);
@@ -147,7 +298,7 @@ test_rev_fail (void)
        GeocodePlace *place;
 
        loc = geocode_location_new (-90, -180, GEOCODE_LOCATION_ACCURACY_UNKNOWN);
-       rev = geocode_reverse_new_for_location (loc);
+       rev = create_reverse (loc, "rev_fail.json");
        g_object_unref (loc);
 
        place = geocode_reverse_resolve (rev, &error);
@@ -158,29 +309,18 @@ test_rev_fail (void)
 }
 
 static void
-add_attr (GHashTable *ht,
-         const char *key,
-         const char *s)
-{
-       GValue *value;
-       value = g_new0 (GValue, 1);
-       g_value_init (value, G_TYPE_STRING);
-       g_value_set_static_string (value, s);
-       g_hash_table_insert (ht, g_strdup (key), value);
-}
-
-static void
 test_xep (void)
 {
-       GHashTable *tp;
+       g_autoptr (GHashTable) tp = NULL, params = NULL;
        GeocodeForward *object;
        GList *res;
        GeocodePlace *place;
        GeocodeLocation *loc;
        GError *error = NULL;
 
+       /* The query parameters we are submitting. */
        tp = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                   g_free, g_free);
+                                   g_free, (GDestroyNotify) free_attr);
        add_attr (tp, "country", "United Kingdom");
        add_attr (tp, "region", "England");
        add_attr (tp, "county", "Surrey");
@@ -188,9 +328,17 @@ test_xep (void)
        add_attr (tp, "postalcode", "GU2 7NU");
        add_attr (tp, "street", "Old Palace Road");
 
-       object = geocode_forward_new_for_params (tp);
-       g_assert (object != NULL);
-       g_hash_table_destroy (tp);
+       /* The query parameters the mock server expects to receive. */
+       params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+       add_attr_string (params, "country", "United Kingdom");
+       add_attr_string (params, "state", "England");
+       add_attr_string (params, "county", "Surrey");
+       add_attr_string (params, "city", "Guildford");
+       add_attr_string (params, "postalcode", "GU2 7NU");
+       add_attr_string (params, "street", "Old Palace Road");
+       add_attr_string (params, "limit", "1");
+
+       object = create_forward_for_params (tp, params, "xep.json");
 
        res = geocode_forward_search (object, &error);
        if (res == NULL) {
@@ -214,13 +362,22 @@ test_xep (void)
 static void
 test_pub (void)
 {
+       g_autoptr (GHashTable) params = NULL;
        GeocodeForward *object;
        GError *error = NULL;
        GList *res;
        GeocodePlace *place;
        GeocodeLocation *loc;
 
-       object = geocode_forward_new_for_string ("9, old palace road, guildford, surrey");
+       /* The query parameters the mock server expects to receive. */
+       params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+       add_attr_string (params, "q", "9, old palace road, guildford, surrey");
+       add_attr_string (params, "limit", "1");
+       add_attr_string (params, "bounded", "0");
+
+       object = create_forward_for_string ("9, old palace road, guildford, surrey",
+                                           params, "pub.json");
+
        geocode_forward_set_answer_count (object, 1);
        res = geocode_forward_search (object, &error);
        if (res == NULL) {
@@ -247,6 +404,7 @@ static void
 test_search (void)
 {
        GeocodeForward *forward;
+       g_autoptr (GHashTable) params = NULL;
        GError *error = NULL;
        GList *results;
        char *old_locale;
@@ -254,7 +412,14 @@ test_search (void)
        old_locale = g_strdup (setlocale(LC_MESSAGES, NULL));
        setlocale (LC_MESSAGES, "en_GB.UTF-8");
 
-       forward = geocode_forward_new_for_string ("paris");
+       /* The query parameters the mock server expects to receive. */
+       params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+       add_attr_string (params, "q", "paris");
+       add_attr_string (params, "limit", "10");
+       add_attr_string (params, "bounded", "0");
+
+       forward = create_forward_for_string ("paris", params, "search.json");
+
        results = geocode_forward_search (forward, &error);
        if (results == NULL) {
                g_warning ("Failed at geocoding: %s", error->message);
@@ -317,8 +482,17 @@ test_search_lat_long (void)
        GeocodePlace *place;
        GeocodeLocation *loc;
        GeocodeBoundingBox *bbox;
+       g_autoptr (GHashTable) params = NULL;
+
+       /* The query parameters the mock server expects to receive. */
+       params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+       add_attr_string (params, "q", "Santa María del Río, San Luis Potosi");
+       add_attr_string (params, "limit", "10");
+       add_attr_string (params, "bounded", "0");
+
+       object = create_forward_for_string ("Santa María del Río, San Luis Potosi",
+                                           params, "search_lat_long.json");
 
-       object = geocode_forward_new_for_string ("Santa María del Río, San Luis Potosi");
        res = geocode_forward_search (object, &error);
        if (res == NULL) {
                g_warning ("Failed at geocoding: %s", error->message);
@@ -361,7 +535,21 @@ test_osm_type (void)
                { "Grand canyon, USA", GEOCODE_PLACE_OSM_TYPE_NODE }
        };
        for (i = 0; i < G_N_ELEMENTS (types); i++) {
-               object = geocode_forward_new_for_string (types[i].search_string);
+               g_autoptr (GHashTable) params = NULL;
+               g_autofree gchar *expected_response_filename = NULL;
+
+               /* The query parameters the mock server expects to receive. */
+               params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+                                               NULL);
+               add_attr_string (params, "q", types[i].search_string);
+               add_attr_string (params, "limit", "10");
+               add_attr_string (params, "bounded", "0");
+
+               expected_response_filename = g_strdup_printf ("osm_type%u.json",
+                                                             i);
+
+               object = create_forward_for_string (types[i].search_string, params,
+                                                   expected_response_filename);
                res = geocode_forward_search (object, &error);
                if (res == NULL) {
                        g_warning ("Failed at geocoding: %s", error->message);
@@ -401,13 +589,22 @@ test_locale_format (void)
        GList *res;
        GeocodePlace *place;
        char *old_locale;
+       g_autoptr (GHashTable) params = NULL;
 
        old_locale = g_strdup (setlocale(LC_ADDRESS, NULL));
 
        /* Set to a locale that has number after street */
        setlocale (LC_ADDRESS, "sv_SE.utf8");
 
-       object = geocode_forward_new_for_string ("Université libre de Bruxelles");
+       /* The query parameters the mock server expects to receive. */
+       params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+       add_attr_string (params, "q", "Université libre de Bruxelles");
+       add_attr_string (params, "limit", "10");
+       add_attr_string (params, "bounded", "0");
+
+       object = create_forward_for_string ("Université libre de Bruxelles",
+                                           params, "locale_format.json");
+
        res = geocode_forward_search (object, &error);
        if (res == NULL) {
                g_warning ("Failed at geocoding: %s", error->message);
@@ -435,12 +632,22 @@ test_locale_name (void)
        GeocodePlace *place;
        GeocodeLocation *loc;
        char *old_locale;
+       g_autoptr (GHashTable) params = NULL;
 
        old_locale = g_strdup (setlocale(LC_MESSAGES, NULL));
 
+       /* The query parameters the mock server expects to receive. */
+       params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+       add_attr_string (params, "q", "moscow");
+       add_attr_string (params, "limit", "10");
+       add_attr_string (params, "bounded", "0");
+
        /* Check Moscow's name in Czech */
        setlocale (LC_MESSAGES, "cs_CZ.UTF-8");
-       object = geocode_forward_new_for_string ("moscow");
+
+       object = create_forward_for_string ("moscow", params,
+                                           "locale_name.json");
+
        res = geocode_forward_search (object, &error);
        if (res == NULL) {
                g_warning ("Failed at geocoding: %s", error->message);
@@ -624,6 +831,7 @@ int main (int argc, char **argv)
        const GOptionEntry entries[] = {
                { "count", 0, 0, G_OPTION_ARG_INT, &answer_count, "Number of answers to get for forward 
searches", NULL },
                { "reverse", 0, 0, G_OPTION_ARG_NONE, &do_rev_geocoding, "Whether to do reverse geocoding for 
the given parameters", NULL },
+               { "enable-network", 0, 0, G_OPTION_ARG_NONE, &enable_network, "Whether to do network queries 
during unit tests, or use recorded results", NULL },
                { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &params, NULL, "[KEY=VALUE...]" },
                { NULL }
        };
diff --git a/geocode-glib/tests/geocode-nominatim-test.c b/geocode-glib/tests/geocode-nominatim-test.c
new file mode 100644
index 0000000..7820475
--- /dev/null
+++ b/geocode-glib/tests/geocode-nominatim-test.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2016 Collabora Ltd.
+ *
+ * The geocode-glib library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The geocode-glib library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301  USA.
+ *
+ * Authors: Aleksander Morgado <aleksander morgado collabora co uk>
+ *          Philip Withnall <philip withnall collabora co uk>
+ */
+
+#include <glib.h>
+#include <libsoup/soup.h>
+
+#include "geocode-glib.h"
+#include "geocode-nominatim-test.h"
+
+struct _GeocodeNominatimTest {
+       GeocodeNominatim parent;
+       GList *cache;
+};
+
+G_DEFINE_TYPE (GeocodeNominatimTest, geocode_nominatim_test, GEOCODE_TYPE_NOMINATIM)
+
+/******************************************************************************/
+
+typedef struct {
+       GHashTable *ht;
+       gchar      *response;
+} CacheItem;
+
+static void
+cache_item_free (CacheItem *item)
+{
+       g_hash_table_unref (item->ht);
+       g_free (item->response);
+       g_slice_free (CacheItem, item);
+}
+
+/* Finds the first item which satisfies the input arguments */
+static CacheItem *
+lookup_cache_item (GeocodeNominatimTest *self,
+                   GHashTable           *ht)
+{
+       GList *l;
+
+       for (l = self->cache; l; l = g_list_next (l)) {
+               CacheItem *item = l->data;
+               gboolean found = TRUE;
+               GHashTableIter iter;
+               gpointer key, value, value2;
+
+               if (g_hash_table_size (item->ht) != g_hash_table_size (ht))
+                       continue;
+
+               g_hash_table_iter_init (&iter, ht);
+               while (found && g_hash_table_iter_next (&iter, &key, &value)) {
+                       found = g_hash_table_lookup_extended (item->ht, key,
+                                                             NULL, (gpointer *) &value2);
+
+                       if (!found)
+                               continue;
+
+                       g_debug ("%s: comparing %s, %s", G_STRFUNC,
+                                (const gchar *) value,
+                                (const gchar *) value2);
+
+                       found = g_str_equal ((const gchar *) value,
+                                            (const gchar *) value2);
+               }
+
+               if (!found)
+                       g_debug ("%s: failed to find %s = %s", G_STRFUNC,
+                                (const gchar *) key, (const gchar *) value);
+
+               if (found)
+                       return item;
+       }
+
+       return NULL;
+}
+
+/*
+ * @self:
+ * @ht: (element-type utf8 utf8) (transfer none):
+ * @response:
+ */
+void
+geocode_nominatim_test_expect_query (GeocodeNominatimTest *self,
+                                     GHashTable           *ht,
+                                     const char           *response)
+{
+       CacheItem *item;
+
+       {
+               GHashTableIter iter;
+               gpointer key, value;
+
+               g_hash_table_iter_init (&iter, ht);
+               while (g_hash_table_iter_next (&iter, &key, &value)) {
+                       g_debug ("%s: %s = %s", G_STRFUNC, (const gchar *) key,
+                                (const gchar *) value);
+               }
+       }
+
+       item = g_slice_new (CacheItem);
+       item->ht = g_hash_table_ref (ht);
+       item->response = g_strdup (response);
+
+       self->cache = g_list_prepend (self->cache, item);
+}
+
+/******************************************************************************/
+
+static gchar *
+common_get_response (GeocodeNominatim  *self,
+                     const gchar       *uri,
+                     GError           **error)
+{
+       CacheItem *item;
+       SoupURI *parsed_uri = NULL;
+       GHashTable *parameters = NULL;
+
+       /* Parse the URI to get its query parameters. */
+       parsed_uri = soup_uri_new (uri);
+       g_assert_nonnull (parsed_uri);
+
+       parameters = soup_form_decode (soup_uri_get_query (parsed_uri));
+       soup_uri_free (parsed_uri);
+
+       {
+               GHashTableIter iter;
+               gpointer key, value;
+
+               g_hash_table_iter_init (&iter, parameters);
+               while (g_hash_table_iter_next (&iter, &key, &value))
+                       g_debug ("%s: %s = %s", G_STRFUNC, (const gchar *) key, (const gchar *) value);
+       }
+
+       /* Drop keys which we don’t care about. */
+       g_assert_true (g_hash_table_remove (parameters, "addressdetails"));
+       g_assert_true (g_hash_table_remove (parameters, "email"));
+       g_assert_true (g_hash_table_remove (parameters, "format"));
+       g_assert_true (g_hash_table_remove (parameters, "accept-language"));
+
+       /* Find the item in the cache. */
+       item = lookup_cache_item (GEOCODE_NOMINATIM_TEST (self), parameters);
+       g_hash_table_unref (parameters);
+
+       if (!item) {
+               g_set_error (error,
+                            G_IO_ERROR,
+                            G_IO_ERROR_NOT_FOUND,
+                            "Location not found");
+               return NULL;
+       }
+
+       return g_strdup (item->response);
+}
+
+static gchar *
+real_query_finish (GeocodeNominatim  *self,
+                   GAsyncResult      *res,
+                   GError           **error)
+{
+       return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+real_query_async (GeocodeNominatim    *self,
+                  const gchar         *uri,
+                  GCancellable        *cancellable,
+                  GAsyncReadyCallback  callback,
+                  gpointer             user_data)
+{
+       GTask *task;
+       gchar *response;
+       GError *error = NULL;
+
+       task = g_task_new (self, cancellable, callback, user_data);
+
+       response = common_get_response (self, uri, &error);
+       if (response == NULL)
+               g_task_return_error (task, error);
+       else
+               g_task_return_pointer (task, response, g_free);
+       g_object_unref (task);
+}
+
+static gchar *
+real_query (GeocodeNominatim  *self,
+            const gchar       *uri,
+            GCancellable      *cancellable,
+            GError           **error)
+{
+       return common_get_response (self, uri, error);
+}
+
+/******************************************************************************/
+
+GeocodeNominatim *
+geocode_nominatim_test_new (void)
+{
+       return GEOCODE_NOMINATIM (g_object_new (GEOCODE_TYPE_NOMINATIM_TEST,
+                                               "base-url", "http://example.invalid";,
+                                               "maintainer-email-address", "maintainer@invalid",
+                                               NULL));
+}
+
+static void
+geocode_nominatim_test_init (GeocodeNominatimTest *object)
+{
+}
+
+static void
+geocode_nominatim_test_finalize (GObject *object)
+{
+       GeocodeNominatimTest *self;
+
+       self = GEOCODE_NOMINATIM_TEST (object);
+
+       g_list_free_full (self->cache, (GDestroyNotify) cache_item_free);
+
+       G_OBJECT_CLASS (geocode_nominatim_test_parent_class)->finalize (object);
+}
+
+static void
+geocode_nominatim_test_class_init (GeocodeNominatimTestClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GeocodeNominatimClass *nominatim_class = GEOCODE_NOMINATIM_CLASS (klass);
+
+       object_class->finalize = geocode_nominatim_test_finalize;
+
+       nominatim_class->query        = real_query;
+       nominatim_class->query_async  = real_query_async;
+       nominatim_class->query_finish = real_query_finish;
+}
diff --git a/geocode-glib/tests/geocode-nominatim-test.h b/geocode-glib/tests/geocode-nominatim-test.h
new file mode 100644
index 0000000..9f6c606
--- /dev/null
+++ b/geocode-glib/tests/geocode-nominatim-test.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Collabora Ltd.
+ *
+ * The geocode-glib library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The geocode-glib library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301  USA.
+ *
+ * Authors: Aleksander Morgado <aleksander morgado collabora co uk>
+ *          Philip Withnall <philip withnall collabora co uk>
+ */
+
+#ifndef GEOCODE_NOMINATIM_TEST_H
+#define GEOCODE_NOMINATIM_TEST_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "geocode-nominatim.h"
+
+G_BEGIN_DECLS
+
+#define GEOCODE_TYPE_NOMINATIM_TEST (geocode_nominatim_test_get_type ())
+G_DECLARE_FINAL_TYPE (GeocodeNominatimTest, geocode_nominatim_test, GEOCODE, NOMINATIM_TEST, 
GeocodeNominatim)
+
+GeocodeNominatim *geocode_nominatim_test_new          (void);
+
+void              geocode_nominatim_test_expect_query (GeocodeNominatimTest *self,
+                                                       GHashTable           *ht,
+                                                       const char           *response);
+
+G_END_DECLS
+
+#endif /* GEOCODE_NOMINATIM_TEST_H */
diff --git a/geocode-glib/tests/locale_format.json b/geocode-glib/tests/locale_format.json
new file mode 100644
index 0000000..f058978
--- /dev/null
+++ b/geocode-glib/tests/locale_format.json
@@ -0,0 +1 @@
+[{"place_id":"23486142","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"2315999088","boundingbox":["50.8126949","50.8127949","4.3794063","4.3795063"],"lat":"50.8127449","lon":"4.3794563","display_name":"Bibliothèque
 de droit et de criminologie, 50, Avenue Franklin Roosevelt - Franklin Rooseveltlaan, Brussels, Ville de 
Bruxelles - Stad Brussel, Brussels-Capital, 1050, 
Belgium","place_rank":"30","category":"amenity","type":"library","importance":0.201,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/amenity_library.p.20.png","address":{"library":"Bibliothèque
 de droit et de criminologie","house_number":"50","road":"Avenue Franklin Roosevelt - Franklin 
Rooseveltlaan","city_district":"Brussels","city":"Ville de Bruxelles - Stad 
Brussel","county":"Brussels-Capital","state":"Brussels-Capital","postcode":"1050","country":"Belgium","country_code":"be"}},{"place_id":"97234613","licence":
 "Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"148808968","boundingbox":["50.8136846","50.8139225","4.3831536","4.3835246"],"lat":"50.8138035","lon":"4.38333908604889","display_name":"Parking
 vélo sécurisé, Avenue Paul Héger - Paul Hégerlaan, Brussels, Ville de Bruxelles - Stad Brussel, 
Brussels-Capital, 1000, 
Belgium","place_rank":"30","category":"amenity","type":"bicycle_parking","importance":0.201,"address":{"bicycle_parking":"Parking
 vélo sécurisé","pedestrian":"Avenue Paul Héger - Paul Hégerlaan","city_district":"Brussels","city":"Ville de 
Bruxelles - Stad 
Brussel","county":"Brussels-Capital","state":"Brussels-Capital","postcode":"1000","country":"Belgium","country_code":"be"}}]
diff --git a/geocode-glib/tests/locale_name.json b/geocode-glib/tests/locale_name.json
new file mode 100644
index 0000000..7c54ce2
--- /dev/null
+++ b/geocode-glib/tests/locale_name.json
@@ -0,0 +1 @@
+[{"place_id":"159575959","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"2555133","boundingbox":["55.4913076","55.9574097","37.290502","37.9674277"],"lat":"55.7506828","lon":"37.6174976","display_name":"Moskva,
 Центральный административный округ, Moskva, Centrální federální okruh, Ruská 
federace","place_rank":16,"category":"place","type":"city","importance":0.81231629038453,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Moskva","state_district":"Центральный
 административный округ","state":"Moskva","country":"Ruská 
federace","country_code":"ru"}},{"place_id":"159148837","licence":"Data © OpenStreetMap contributors, ODbL 
1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"102269","boundingbox":["55.1421745","56.0212238","36.8031012","37
 .9674277"],"lat":"55.4792046","lon":"37.3273304","display_name":"Moskva, Centrální federální okruh, Ruská 
federace","place_rank":"8","category":"boundary","type":"administrative","importance":0.81231629038453,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_boundary_administrative.p.20.png","address":{"state":"Moskva","country":"Ruská
 federace","country_code":"ru"}},{"place_id":"158661492","licence":"Data © OpenStreetMap contributors, ODbL 
1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"121430","boundingbox":["46.710912","46.758882","-117.0396979","-116.9620679"],"lat":"46.7323875","lon":"-117.000165","display_name":"Moscow,
 Latah County, Idaho, Spojené státy 
americké","place_rank":16,"category":"place","type":"city","importance":0.53629964602682,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Moscow","county":"Latah
 County","state":"Idaho","country":"Sp
 ojené státy americké","country_code":"us"}},{"place_id":"83209933","licence":"Data © OpenStreetMap 
contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"87186419","boundingbox":["25.2302669","25.2325261","55.1643501","55.1667109"],"lat":"25.2313998","lon":"55.1655538746233","display_name":"Moscow,
 Dubaj, دبي‎, Spojené arabské 
emiráty","place_rank":"17","category":"place","type":"island","importance":0.425,"address":{"island":"Moscow","city":"Dubaj","state":"دبي‎","country":"Spojené
 arabské emiráty","country_code":"ae"}},{"place_id":"158830575","licence":"Data © OpenStreetMap contributors, 
ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"188588","boundingbox":["41.332327","41.359539","-75.5571869","-75.5055579"],"lat":"41.3367497","lon":"-75.518519","display_name":"Moscow,
 Lackawanna County, Pensylvánie, Spojené státy americké","place_rank":"16","category":"boundary","type":"a
 
dministrative","importance":0.40496966945241,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_boundary_administrative.p.20.png","address":{"city":"Moscow","county":"Lackawanna
 County","state":"Pensylvánie","country":"Spojené státy 
americké","country_code":"us"}},{"place_id":"453497","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"157606151","boundingbox":["39.5237014","39.5637014","-79.0250272","-78.9850272"],"lat":"39.5437014","lon":"-79.0050272","display_name":"Moscow,
 Allegany County, Maryland, Spojené státy 
americké","place_rank":"19","category":"place","type":"hamlet","importance":0.37594331946278,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_village.p.20.png","address":{"hamlet":"Moscow","county":"Allegany
 County","state":"Maryland","country":"Spojené státy 
americké","country_code":"us"}},{"place_id":"421984","licence":"Data © Open
 StreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"153805006","boundingbox":["37.3914401","37.4314401","-89.0725736","-89.0325736"],"lat":"37.4114401","lon":"-89.0525736","display_name":"Moscow,
 Union County, Illinois, Spojené státy 
americké","place_rank":"19","category":"place","type":"hamlet","importance":0.375,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_village.p.20.png","address":{"hamlet":"Moscow","county":"Union
 County","state":"Illinois","country":"Spojené státy 
americké","country_code":"us"}},{"place_id":"436343","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"154194549","boundingbox":["42.0302346","42.0702346","-84.5298798","-84.4898798"],"lat":"42.0502346","lon":"-84.5098798","display_name":"Moscow,
 Hillsdale County, Michigan, Spojené státy americké","place_rank":"19","category":"place","type":
 
"village","importance":0.375,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_village.p.20.png","address":{"village":"Moscow","county":"Hillsdale
 County","state":"Michigan","country":"Spojené státy 
americké","country_code":"us"}},{"place_id":"390992","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"151964024","boundingbox":["43.6871833","43.7271833","-93.1182537","-93.0782537"],"lat":"43.7071833","lon":"-93.0982537","display_name":"Moscow,
 Freeborn County, Minnesota, Spojené státy 
americké","place_rank":"19","category":"place","type":"village","importance":0.375,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_village.p.20.png","address":{"village":"Moscow","county":"Freeborn
 County","state":"Minnesota","country":"Spojené státy 
americké","country_code":"us"}},{"place_id":"377384","licence":"Data © OpenStreetMap contributors, ODbL 1.0. h
 
ttp:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"151724752","boundingbox":["39.1463923","39.1863923","-94.5618989","-94.5218989"],"lat":"39.1663923","lon":"-94.5418989","display_name":"Moscow,
 Clay County, Missouri, Spojené státy 
americké","place_rank":"19","category":"place","type":"hamlet","importance":0.375,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_village.p.20.png","address":{"hamlet":"Moscow","county":"Clay
 County","state":"Missouri","country":"Spojené státy americké","country_code":"us"}}]
diff --git a/geocode-glib/tests/osm_type0.json b/geocode-glib/tests/osm_type0.json
new file mode 100644
index 0000000..351995e
--- /dev/null
+++ b/geocode-glib/tests/osm_type0.json
@@ -0,0 +1 @@
+[{"place_id":"115172167","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"223642382","boundingbox":["59.8539981","59.854485","17.6342631","17.6347087"],"lat":"59.8541808","lon":"17.6345568","display_name":"Drottning
 Christinas väg, Triangeln, Fjärdingen, Uppsala, Landskapet Uppland, Uppsala län, Svealand, 752 37, 
Sweden","place_rank":"26","category":"highway","type":"residential","importance":0.4,"address":{"road":"Drottning
 Christinas 
väg","neighbourhood":"Triangeln","suburb":"Fjärdingen","city":"Uppsala","county":"Uppsala","state_district":"Landskapet
 Uppland","state":"Uppsala län","postcode":"752 37","country":"Sweden","country_code":"se"}}]
diff --git a/geocode-glib/tests/osm_type1.json b/geocode-glib/tests/osm_type1.json
new file mode 100644
index 0000000..679b049
--- /dev/null
+++ b/geocode-glib/tests/osm_type1.json
@@ -0,0 +1 @@
+[{"place_id":"159134167","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"161653","boundingbox":["45.9350359","49.0004918","-104.0492649","-96.5543974"],"lat":"47.6201461","lon":"-100.5407369","display_name":"North
 Dakota, United States of 
America","place_rank":"8","category":"boundary","type":"administrative","importance":0.80989374269226,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_boundary_administrative.p.20.png","address":{"state":"North
 Dakota","country":"United States of America","country_code":"us"}},{"place_id":"63256184","licence":"Data © 
OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"15356028","boundingbox":["30.531778","30.531948","-98.3573339","-98.3571539"],"lat":"30.531948","lon":"-98.3573339","display_name":"North
 Dakota, Horseshoe Bay, Llano County, Texas, 78654, United States of America","pl
 ace_rank":"26","category":"highway","type":"residential","importance":0.3,"address":{"road":"North 
Dakota","city":"Horseshoe Bay","county":"Llano County","state":"Texas","postcode":"78654","country":"United 
States of America","country_code":"us"}},{"place_id":"66342385","licence":"Data © OpenStreetMap contributors, 
ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"18668411","boundingbox":["37.763188","37.76417","-92.1232629","-92.1106879"],"lat":"37.764169","lon":"-92.1168369","display_name":"North
 Dakota, Fort Leonard Wood, Pulaski County, Missouri, 65473, United States of 
America","place_rank":"26","category":"highway","type":"residential","importance":0.3,"address":{"road":"North
 Dakota","locality":"Fort Leonard Wood","county":"Pulaski 
County","state":"Missouri","postcode":"65473","country":"United States of 
America","country_code":"us"}},{"place_id":"61183298","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetm
 
ap.org\/copyright","osm_type":"way","osm_id":"9901941","boundingbox":["44.011103","44.012716","-97.5253239","-97.5253139"],"lat":"44.012031","lon":"-97.5253139","display_name":"North
 Dakota, Howard, Miner County, South Dakota, 57349, United States of 
America","place_rank":"26","category":"highway","type":"residential","importance":0.3,"address":{"road":"North
 Dakota","city":"Howard","county":"Miner County","state":"South Dakota","postcode":"57349","country":"United 
States of America","country_code":"us"}}]
diff --git a/geocode-glib/tests/osm_type2.json b/geocode-glib/tests/osm_type2.json
new file mode 100644
index 0000000..f9d16dd
--- /dev/null
+++ b/geocode-glib/tests/osm_type2.json
@@ -0,0 +1 @@
+[{"place_id":"347666","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"150980731","boundingbox":["36.0765604","36.1165604","-112.118494","-112.078494"],"lat":"36.0965604","lon":"-112.098494","display_name":"Grand
 Canyon, Coconino County, Arizona, United States of 
America","place_rank":"19","category":"place","type":"hamlet","importance":0.475,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_village.p.20.png","address":{"hamlet":"Grand
 Canyon","county":"Coconino County","state":"Arizona","country":"United States of 
America","country_code":"us"}},{"place_id":"63362341","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"14424313","boundingbox":["35.092298","35.092657","-106.4879419","-106.4872739"],"lat":"35.092657","lon":"-106.4879419","display_name":"Grand
 Canyon, Chelwood Park, Albuquerque, Bernal
 illo County, New Mexico, 87123, United States of 
America","place_rank":"26","category":"highway","type":"residential","importance":0.3,"address":{"road":"Grand
 Canyon","suburb":"Chelwood Park","city":"Albuquerque","county":"Bernalillo County","state":"New 
Mexico","postcode":"87123","country":"United States of 
America","country_code":"us"}},{"place_id":"61337636","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"13305122","boundingbox":["33.933346","33.9347728","-117.8923901","-117.891799"],"lat":"33.9341992","lon":"-117.891799","display_name":"Grand
 Canyon, Downtown Brea, Brea, Orange County, California, 92821, United States of 
America","place_rank":"26","category":"highway","type":"residential","importance":0.3,"address":{"road":"Grand
 Canyon","suburb":"Downtown Brea","city":"Brea","county":"Orange 
County","state":"California","postcode":"92821","country":"United States of America","country_code":"
 us"}},{"place_id":"102872428","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"171147658","boundingbox":["36.0567225","36.056892","-112.1369029","-112.1364479"],"lat":"36.05681405","lon":"-112.136675398263","display_name":"Grand
 Canyon, Village Loop Drive, Paiute Apartments, Grand Canyon Village, Coconino County, Arizona, 86023, United 
States of 
America","place_rank":"30","category":"railway","type":"station","importance":0.201,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/transport_train_station2.p.20.png","address":{"station":"Grand
 Canyon","road":"Village Loop Drive","neighbourhood":"Paiute Apartments","hamlet":"Grand Canyon 
Village","county":"Coconino County","state":"Arizona","postcode":"86023","country":"United States of 
America","country_code":"us"}}]
diff --git a/geocode-glib/tests/pub.json b/geocode-glib/tests/pub.json
new file mode 100644
index 0000000..d466b84
--- /dev/null
+++ b/geocode-glib/tests/pub.json
@@ -0,0 +1 @@
+[{"place_id":"56566537","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"4317978","boundingbox":["51.2366463","51.2370686","-0.5936966","-0.5896438"],"lat":"51.2368747","lon":"-0.5912357","display_name":"Old
 Palace Road, Guildford Park, Guildford, Surrey, South East, England, GU2 7PJ, United 
Kingdom","place_rank":"26","category":"highway","type":"residential","importance":0.6,"address":{"road":"Old 
Palace Road","suburb":"Guildford Park","town":"Guildford","county":"Surrey","state_district":"South 
East","state":"England","postcode":"GU2 7PJ","country":"United Kingdom","country_code":"gb"}}]
diff --git a/geocode-glib/tests/rev.json b/geocode-glib/tests/rev.json
new file mode 100644
index 0000000..08a58e7
--- /dev/null
+++ b/geocode-glib/tests/rev.json
@@ -0,0 +1 @@
+{"place_id":"147857","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"28393339","lat":"51.2370361","lon":"-0.5894833","display_name":"The
 Astolat, Old Palace Road, Guildford Park, Guildford, Surrey, South East, England, GU2 7NU, United 
Kingdom","address":{"pub":"The Astolat","road":"Old Palace Road","suburb":"Guildford 
Park","town":"Guildford","county":"Surrey","state_district":"South East","state":"England","postcode":"GU2 
7NU","country":"United 
Kingdom","country_code":"gb"},"boundingbox":["51.2369361","51.2371361","-0.5895833","-0.5893833"]}
diff --git a/geocode-glib/tests/rev_fail.json b/geocode-glib/tests/rev_fail.json
new file mode 100644
index 0000000..82728eb
--- /dev/null
+++ b/geocode-glib/tests/rev_fail.json
@@ -0,0 +1 @@
+{"error":"Unable to geocode"}
diff --git a/geocode-glib/tests/search.json b/geocode-glib/tests/search.json
new file mode 100644
index 0000000..3c7167b
--- /dev/null
+++ b/geocode-glib/tests/search.json
@@ -0,0 +1 @@
+[{"place_id":"158768940","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"7444","boundingbox":["48.8155755","48.902156","2.224122","2.4697602"],"lat":"48.8566101","lon":"2.3514992","display_name":"Paris,
 Ile-de-France, 
France","place_rank":16,"category":"place","type":"city","importance":0.96893459932191,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Paris","county":"Paris","state":"Ile-de-France","country":"France","country_code":"fr"}},{"place_id":"159011327","licence":"Data
 © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"71525","boundingbox":["48.8155755","48.902156","2.224122","2.4697602"],"lat":"48.85881005","lon":"2.32003101155031","display_name":"Paris,
 Ile-de-France, France","place_rank":"12","category":"boundary","type":"administrative","importance":0.96893
 
459932191,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_boundary_administrative.p.20.png","address":{"county":"Paris","state":"Ile-de-France","country":"France","country_code":"fr"}},{"place_id":"72390777","licence":"Data
 © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"33063046","boundingbox":["35.26725","35.3065029","-93.7618069","-93.6750829"],"lat":"35.2920325","lon":"-93.7299172","display_name":"Paris,
 Logan County, Arkansas, United States of 
America","place_rank":16,"category":"place","type":"city","importance":0.67385884862688,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Paris","county":"Logan
 County","state":"Arkansas","country":"United States of 
America","country_code":"us"}},{"place_id":"72252999","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_i
 
d":"33299478","boundingbox":["33.611853","33.738378","-95.6279279","-95.4354549"],"lat":"33.6617962","lon":"-95.5555129","display_name":"Paris,
 Lamar County, Texas, United States of 
America","place_rank":16,"category":"place","type":"city","importance":0.54374443751163,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Paris","county":"Lamar
 County","state":"Texas","country":"United States of 
America","country_code":"us"}},{"place_id":"158385699","licence":"Data © OpenStreetMap contributors, ODbL 
1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"130722","boundingbox":["38.164922","38.238271","-84.3073259","-84.2320889"],"lat":"38.2097987","lon":"-84.2529868","display_name":"Paris,
 Bourbon County, Kentucky, United States of 
America","place_rank":16,"category":"place","type":"city","importance":0.5108263210417,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.
 p.20.png","address":{"city":"Paris","county":"Bourbon County","state":"Kentucky","country":"United States of 
America","country_code":"us"}},{"place_id":"17580742","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"1688891876","boundingbox":["36.1119519","36.1120519","-115.1727108","-115.1726108"],"lat":"36.1120019","lon":"-115.1726608","display_name":"Paris,
 South Las Vegas Boulevard, Hughes Center, Paradise, Clark County, Nevada, 89109, United States of 
America","place_rank":"30","category":"highway","type":"bus_stop","importance":0.4846342182247,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/transport_bus_stop2.p.20.png","address":{"bus_stop":"Paris","road":"South
 Las Vegas Boulevard","suburb":"Hughes Center","locality":"Paradise","county":"Clark 
County","state":"Nevada","postcode":"89109","country":"United States of 
America","country_code":"us"}},{"place_id":"728615","licence":"
 Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"257763716","boundingbox":["43.1532336","43.2332336","-80.4242806","-80.3442806"],"lat":"43.1932336","lon":"-80.3842806","display_name":"Paris,
 Ontario, 
Canada","place_rank":"18","category":"place","type":"town","importance":0.46561345354774,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_town.p.20.png","address":{"town":"Paris","state":"Ontario","country":"Canada","country_code":"ca"}},{"place_id":"159272686","licence":"Data
 © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"140787","boundingbox":["39.469158","39.489278","-92.0214799","-91.9916789"],"lat":"39.4808721","lon":"-92.001281","display_name":"Paris,
 Monroe County, Missouri, United States of 
America","place_rank":16,"category":"place","type":"city","importance":0.44025131828771,"icon":"https:\/\/nominatim.opens
 treetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Paris","county":"Monroe 
County","state":"Missouri","country":"United States of 
America","country_code":"us"}},{"place_id":"158676472","licence":"Data © OpenStreetMap contributors, ODbL 
1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"126166","boundingbox":["39.581423","39.648578","-87.7210459","-87.6505409"],"lat":"39.611146","lon":"-87.6961373","display_name":"Paris,
 Edgar County, Illinois, United States of 
America","place_rank":16,"category":"place","type":"city","importance":0.43634000491239,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Paris","county":"Edgar
 County","state":"Illinois","country":"United States of 
America","country_code":"us"}},{"place_id":"159290077","licence":"Data © OpenStreetMap contributors, ODbL 
1.0. http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"197171"
 
,"boundingbox":["36.266003","36.329016","-88.3671129","-88.2650669"],"lat":"36.3020023","lon":"-88.3267106","display_name":"Paris,
 Henry County, Tennessee, United States of 
America","place_rank":16,"category":"place","type":"city","importance":0.43634000491239,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Paris","county":"Henry
 County","state":"Tennessee","country":"United States of America","country_code":"us"}}]
diff --git a/geocode-glib/tests/search_lat_long.json b/geocode-glib/tests/search_lat_long.json
new file mode 100644
index 0000000..c380328
--- /dev/null
+++ b/geocode-glib/tests/search_lat_long.json
@@ -0,0 +1 @@
+[{"place_id":"159520794","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"5606308","boundingbox":["21.5057892","21.9645472","-100.8575959","-100.162833"],"lat":"21.7352338","lon":"-100.738270891867","display_name":"Santa
 María del Río, San Luis Potosi, 
Mexico","place_rank":"12","category":"boundary","type":"administrative","importance":1.15,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_boundary_administrative.p.20.png","address":{"county":"Santa
 María del Río","state":"San Luis 
Potosi","country":"Mexico","country_code":"mx"}},{"place_id":"119732203","licence":"Data © OpenStreetMap 
contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"231258663","boundingbox":["21.7868615","21.8194719","-100.7566734","-100.718233"],"lat":"21.8036408","lon":"-100.736291573011","display_name":"Santa
 Maria Del Rio, Santa María del Río, San Luis 
 Potosi, 
Mexico","place_rank":"16","category":"place","type":"city","importance":1.05,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Santa
 Maria Del Rio","county":"Santa María del Río","state":"San Luis 
Potosi","country":"Mexico","country_code":"mx"}},{"place_id":"195943025","licence":"Data © OpenStreetMap 
contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"node","osm_id":"4442589288","boundingbox":["21.7585605","21.8385605","-100.7769914","-100.6969914"],"lat":"21.7985605","lon":"-100.7369914","display_name":"Santa
 María del Río, San Luis Potosi, 
Mexico","place_rank":"18","category":"place","type":"town","importance":1,"icon":"https:\/\/nominatim.openstreetmap.org\/images\/mapicons\/poi_place_town.p.20.png","address":{"town":"Santa
 María del Río","county":"Santa María del Río","state":"San Luis 
Potosi","country":"Mexico","country_code":"mx"}},{"place_id":"115892645","licence":"D
 ata © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"226309582","boundingbox":["22.181339","22.1819652","-100.9556258","-100.9549784"],"lat":"22.1817018","lon":"-100.9553991","display_name":"Santa
 Maria del Rio, Colonia San Felipe, Soledad de Graciano Sánchez, San Luis Potosi, 78437, 
Mexico","place_rank":"26","category":"highway","type":"residential","importance":0.6,"address":{"road":"Santa 
Maria del Rio","residential":"Colonia San Felipe","town":"Soledad de Graciano Sánchez","county":"Soledad de 
Graciano Sánchez","state":"San Luis Potosi","postcode":"78437","country":"Mexico","country_code":"mx"}}]
diff --git a/geocode-glib/tests/xep.json b/geocode-glib/tests/xep.json
new file mode 100644
index 0000000..e51631c
--- /dev/null
+++ b/geocode-glib/tests/xep.json
@@ -0,0 +1 @@
+[{"place_id":"56938009","licence":"Data © OpenStreetMap contributors, ODbL 1.0. 
http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"6072662","boundingbox":["51.2370686","51.2372886","-0.5896438","-0.5891985"],"lat":"51.2371333","lon":"-0.5894036","display_name":"Old
 Palace Road, Guildford Park, Guildford, Surrey, South East, England, GU2 7NU, United 
Kingdom","place_rank":"26","category":"highway","type":"residential","importance":1.13,"address":{"road":"Old 
Palace Road","suburb":"Guildford Park","town":"Guildford","county":"Surrey","state_district":"South 
East","state":"England","postcode":"GU2 7NU","country":"United Kingdom","country_code":"gb"}}]


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