From 6bfad6d01f9ab3216af935faba67fb5003f3ea96 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 19 Nov 2021 15:34:38 +0000 Subject: tests: Move duplicate units into their own suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The duplicate tests modify the environment, and impose ordering on the general test suite. Instead of modifying the environment inside the tests—which comes with its own set of threading issues—we can split the tests into a separate binary, and set up the environment when executing the test. --- libgweather/tests/duplicates.c | 242 +++++++++++++++++++++++++++++++++++ libgweather/tests/meson.build | 62 ++++++--- libgweather/tests/test_libgweather.c | 137 -------------------- 3 files changed, 284 insertions(+), 157 deletions(-) create mode 100644 libgweather/tests/duplicates.c (limited to 'libgweather/tests') diff --git a/libgweather/tests/duplicates.c b/libgweather/tests/duplicates.c new file mode 100644 index 0000000..40204de --- /dev/null +++ b/libgweather/tests/duplicates.c @@ -0,0 +1,242 @@ +/* duplicates.c: Check for duplicates in the locations database + * + * SPDX-FileCopyrightText: 2017 Bastien Nocera + * SPDX-FileCopyrightText: 2021 Emmanuele Bassi + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include + +/* We use internal API */ +#include "gweather-private.h" + +extern void +_gweather_location_reset_world (void); + +/* Set up the temporary directory with the GSettings schemas */ +static char * +setup_gsettings (void) +{ + char *tmpdir, *schema_text, *dest, *cmdline; + int result; + + /* Create the installed schemas directory */ + GError *error = NULL; + tmpdir = g_dir_make_tmp ("libgweather-test-XXXXXX", &error); + g_assert_no_error (error); + + g_test_message ("Using temporary directory: %s", tmpdir); + + /* Copy the schemas files */ + g_assert_true (g_file_get_contents (SCHEMAS_BUILDDIR "/org.gnome.GWeather4.enums.xml", &schema_text, NULL, NULL)); + dest = g_build_filename (tmpdir, "org.gnome.GWeather4.enums.xml", NULL); + g_assert_true (g_file_set_contents (dest, schema_text, -1, NULL)); + g_free (dest); + g_free (schema_text); + + g_assert_true (g_file_get_contents (SCHEMASDIR "/org.gnome.GWeather4.gschema.xml", &schema_text, NULL, NULL)); + dest = g_build_filename (tmpdir, "org.gnome.GWeather4.gschema.xml", NULL); + g_assert_true (g_file_set_contents (dest, schema_text, -1, NULL)); + g_free (dest); + g_free (schema_text); + + /* Compile the schemas */ + cmdline = g_strdup_printf ("glib-compile-schemas --targetdir=%s " + "--schema-file=%s/org.gnome.GWeather4.enums.xml " + "--schema-file=%s/org.gnome.GWeather4.gschema.xml", + tmpdir, + SCHEMAS_BUILDDIR, + SCHEMASDIR); + g_assert_true (g_spawn_command_line_sync (cmdline, NULL, NULL, &result, NULL)); + g_assert_cmpint (result, ==, 0); + g_free (cmdline); + + /* Set envvar */ + g_setenv ("GSETTINGS_SCHEMA_DIR", tmpdir, TRUE); + + return tmpdir; +} + +/* Tear down the temporary directory with the GSettings schemas */ +static void +teardown_gsettings (const char *schemas_dir) +{ + char *dest = NULL; + + dest = g_build_filename (schemas_dir, "org.gnome.GWeather4.enums.xml", NULL); + g_assert_no_errno (g_unlink (dest)); + g_free (dest); + + dest = g_build_filename (schemas_dir, "org.gnome.GWeather4.gschema.xml", NULL); + g_assert_no_errno (g_unlink (dest)); + g_free (dest); + + dest = g_build_filename (schemas_dir, "gschemas.compiled", NULL); + g_assert_no_errno (g_unlink (dest)); + g_free (dest); + + g_assert_no_errno (g_rmdir (schemas_dir)); +} + +static void +check_bad_duplicate_weather_stations (gpointer key, + gpointer value, + gpointer user_data) +{ + GPtrArray *stations = value; + GHashTable *dedup; + guint i; + + if (stations->len == 1) + goto out; + + dedup = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + for (i = 0; i < stations->len; i++) { + GWeatherLocation *location = g_ptr_array_index (stations, i); + + double latitude, longitude; + gweather_location_get_coords (location, &latitude, &longitude); + + char *coords = g_strdup_printf ("%.10lf %.10lf", latitude, longitude); + g_hash_table_insert (dedup, coords, GUINT_TO_POINTER (1)); + } + + if (g_hash_table_size (dedup) > 1) { + g_test_message ("Airport '%s' is defined %u times in different ways\n", + (const char *) key, + stations->len); + g_test_fail (); + } + + g_hash_table_destroy (dedup); + +out: + g_ptr_array_free (stations, TRUE); +} + +static void +test_bad_duplicate_weather_stations_children (GWeatherLocation *location, + GHashTable *stations_ht) +{ + g_autoptr (GWeatherLocation) child = NULL; + while ((child = gweather_location_next_child (location, child)) != NULL) { + if (gweather_location_get_level (child) == GWEATHER_LOCATION_WEATHER_STATION) { + GPtrArray *stations; + const char *code; + + code = gweather_location_get_code (child); + + stations = g_hash_table_lookup (stations_ht, code); + if (!stations) { + stations = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + g_hash_table_insert (stations_ht, g_strdup (code), stations); + } + g_ptr_array_add (stations, g_object_ref (child)); + } else { + test_bad_duplicate_weather_stations_children (child, stations_ht); + } + } +} + +static void +test_bad_duplicate_weather_stations (void) +{ + g_autoptr (GWeatherLocation) world = NULL; + GHashTable *stations_ht; + + world = gweather_location_get_world (); + g_assert_nonnull (world); + + stations_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) NULL); + test_bad_duplicate_weather_stations_children (world, stations_ht); + + g_hash_table_foreach (stations_ht, check_bad_duplicate_weather_stations, NULL); + + g_hash_table_unref (stations_ht); + + g_clear_object (&world); + _gweather_location_reset_world (); +} + +static void +test_duplicate_weather_stations_children (GWeatherLocation *location) +{ + g_autoptr (GHashTable) stations_ht = NULL; + + g_autoptr (GWeatherLocation) child = NULL; + while ((child = gweather_location_next_child (location, child)) != NULL) { + if (gweather_location_get_level (child) == GWEATHER_LOCATION_WEATHER_STATION) { + const char *code; + + code = gweather_location_get_code (child); + if (stations_ht == NULL) { + stations_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) NULL); + } else { + gboolean exists; + + exists = GPOINTER_TO_INT (g_hash_table_lookup (stations_ht, code)); + if (exists) { + GWeatherLocationLevel parent_level; + + parent_level = gweather_location_get_level (location); + g_test_message ("Duplicate weather station '%s' in %s (level '%s')\n", + code, + gweather_location_get_name (location), + gweather_location_level_to_string (parent_level)); + g_test_fail (); + return; + } + } + + g_hash_table_insert (stations_ht, g_strdup (code), GINT_TO_POINTER (1)); + } else { + test_duplicate_weather_stations_children (child); + } + } +} + +static void +test_duplicate_weather_stations (void) +{ + g_autoptr (GWeatherLocation) world = NULL; + + world = gweather_location_get_world (); + g_assert_nonnull (world); + + test_duplicate_weather_stations_children (world); + + g_clear_object (&world); + _gweather_location_reset_world (); +} + +int +main (int argc, + char *argv[]) +{ + setlocale (LC_ALL, ""); + + g_test_init (&argc, &argv, NULL); + g_test_bug_base ("http://gitlab.gnome.org/GNOME/libgweather/issues/"); + + char *schemas_dir = setup_gsettings (); + + /* Modifies environment, so needs to run last */ + g_test_add_func ("/weather/bad_duplicate_weather_stations", test_bad_duplicate_weather_stations); + g_test_add_func ("/weather/duplicate_weather_stations", test_duplicate_weather_stations); + + int res = g_test_run (); + + teardown_gsettings (schemas_dir); + + g_free (schemas_dir); + + return res; +} diff --git a/libgweather/tests/meson.build b/libgweather/tests/meson.build index 5018326..4ed6a3d 100644 --- a/libgweather/tests/meson.build +++ b/libgweather/tests/meson.build @@ -1,26 +1,48 @@ -test_cargs = [ +gweather_test_cargs = [ '-DTEST_LOCATIONS="@0@"'.format(locations_bin.full_path()), '-DSCHEMASDIR="@0@/schemas"'.format(meson.source_root()), '-DSCHEMAS_BUILDDIR="@0@/schemas"'.format(meson.build_root()), ] -test_env = environment() -test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) -test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) -test_env.set('GIO_USE_VFS', 'local') -test_env.set('GSETTINGS_BACKED', 'memory') -test_env.set('G_ENABLE_DIAGNOSTIC', '0') -test_env.set('LIBGWEATHER_LOCATIONS_PATH', locations_bin.full_path()) +gweather_test_env = environment() +gweather_test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) +gweather_test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) +gweather_test_env.set('GIO_USE_VFS', 'local') +gweather_test_env.set('GSETTINGS_BACKED', 'memory') +gweather_test_env.set('G_ENABLE_DIAGNOSTIC', '0') +gweather_test_env.set('LIBGWEATHER_LOCATIONS_PATH', locations_bin.full_path()) -test('test_libgweather', - executable('test_libgweather', - sources: ['test_libgweather.c'], - c_args: test_cargs, - dependencies: libgweather_static_dep, - install: false, - ), - args: ['--tap', '-k'], - protocol: 'tap', - env: test_env, - depends: [locations_bin], -) +gweather_tests = [ + { 'name': 'test_libgweather' }, + { + 'name': 'duplicates', + 'env': { + 'LIBGWEATHER_LOCATIONS_NO_NEAREST': '1', + }, + }, +] + +foreach t: gweather_tests + test_name = t['name'] + test_sources = [test_name + '.c'] + t.get('sources', []) + test_c_args = gweather_test_cargs + t.get('c_args', []) + test_env = gweather_test_env + + extra_env = t.get('env', {}) + foreach var, value: extra_env + test_env.set(var, value) + endforeach + + test(test_name, + executable(test_name, + sources: test_sources, + c_args: test_c_args, + dependencies: libgweather_static_dep, + install: false, + ), + args: ['--tap', '-k'], + protocol: 'tap', + env: test_env, + depends: [locations_bin], + ) +endforeach diff --git a/libgweather/tests/test_libgweather.c b/libgweather/tests/test_libgweather.c index c7d07a9..7fa4408 100644 --- a/libgweather/tests/test_libgweather.c +++ b/libgweather/tests/test_libgweather.c @@ -553,141 +553,6 @@ test_utc_sunset (void) _gweather_location_reset_world (); } -static void -check_bad_duplicate_weather_stations (gpointer key, - gpointer value, - gpointer user_data) -{ - GPtrArray *stations = value; - GHashTable *dedup; - guint i; - - if (stations->len == 1) - goto out; - - dedup = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - for (i = 0; i < stations->len; i++) { - GWeatherLocation *location = g_ptr_array_index (stations, i); - - double latitude, longitude; - gweather_location_get_coords (location, &latitude, &longitude); - - char *coords = g_strdup_printf ("%.10lf %.10lf", latitude, longitude); - g_hash_table_insert (dedup, coords, GUINT_TO_POINTER (1)); - } - - if (g_hash_table_size (dedup) > 1) { - g_test_message ("Airport '%s' is defined %u times in different ways\n", - (const char *) key, - stations->len); - g_test_fail (); - } - - g_hash_table_destroy (dedup); - -out: - g_ptr_array_free (stations, TRUE); -} - -static void -test_bad_duplicate_weather_stations_children (GWeatherLocation *location, - GHashTable *stations_ht) -{ - g_autoptr (GWeatherLocation) child = NULL; - while ((child = gweather_location_next_child (location, child)) != NULL) { - if (gweather_location_get_level (child) == GWEATHER_LOCATION_WEATHER_STATION) { - GPtrArray *stations; - const char *code; - - code = gweather_location_get_code (child); - - stations = g_hash_table_lookup (stations_ht, code); - if (!stations) { - stations = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); - g_hash_table_insert (stations_ht, g_strdup (code), stations); - } - g_ptr_array_add (stations, g_object_ref (child)); - } else { - test_bad_duplicate_weather_stations_children (child, stations_ht); - } - } -} - -static void -test_bad_duplicate_weather_stations (void) -{ - g_autoptr (GWeatherLocation) world = NULL; - GHashTable *stations_ht; - - g_setenv ("LIBGWEATHER_LOCATIONS_NO_NEAREST", "1", TRUE); - world = gweather_location_get_world (); - g_assert_nonnull (world); - - stations_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) NULL); - test_bad_duplicate_weather_stations_children (world, stations_ht); - - g_hash_table_foreach (stations_ht, check_bad_duplicate_weather_stations, NULL); - - g_hash_table_unref (stations_ht); - - g_unsetenv ("LIBGWEATHER_LOCATIONS_NO_NEAREST"); - g_clear_object (&world); - _gweather_location_reset_world (); -} - -static void -test_duplicate_weather_stations_children (GWeatherLocation *location) -{ - g_autoptr (GHashTable) stations_ht = NULL; - - g_autoptr (GWeatherLocation) child = NULL; - while ((child = gweather_location_next_child (location, child)) != NULL) { - if (gweather_location_get_level (child) == GWEATHER_LOCATION_WEATHER_STATION) { - const char *code; - - code = gweather_location_get_code (child); - if (stations_ht == NULL) { - stations_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) NULL); - } else { - gboolean exists; - - exists = GPOINTER_TO_INT (g_hash_table_lookup (stations_ht, code)); - if (exists) { - GWeatherLocationLevel parent_level; - - parent_level = gweather_location_get_level (location); - g_test_message ("Duplicate weather station '%s' in %s (level '%s')\n", - code, - gweather_location_get_name (location), - gweather_location_level_to_string (parent_level)); - g_test_fail (); - return; - } - } - - g_hash_table_insert (stations_ht, g_strdup (code), GINT_TO_POINTER (1)); - } else { - test_duplicate_weather_stations_children (child); - } - } -} - -static void -test_duplicate_weather_stations (void) -{ - g_autoptr (GWeatherLocation) world = NULL; - - g_setenv ("LIBGWEATHER_LOCATIONS_NO_NEAREST", "1", TRUE); - world = gweather_location_get_world (); - g_assert_nonnull (world); - - test_duplicate_weather_stations_children (world); - - g_unsetenv ("LIBGWEATHER_LOCATIONS_NO_NEAREST"); - g_clear_object (&world); - _gweather_location_reset_world (); -} - static void test_location_names (void) { @@ -904,8 +769,6 @@ main (int argc, char *argv[]) g_test_add_func ("/weather/utc_sunset", test_utc_sunset); g_test_add_func ("/weather/weather-loop-use-after-free", test_weather_loop_use_after_free); /* Modifies environment, so needs to run last */ - g_test_add_func ("/weather/bad_duplicate_weather_stations", test_bad_duplicate_weather_stations); - g_test_add_func ("/weather/duplicate_weather_stations", test_duplicate_weather_stations); g_test_add_func ("/weather/location-names", test_location_names); g_test_add_func ("/weather/walk_world", test_walk_world); -- cgit v1.2.1