[libgweather] tests: Check locations against METAR database
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgweather] tests: Check locations against METAR database
- Date: Fri, 8 Dec 2017 18:16:13 +0000 (UTC)
commit a3028c23f6b4daec6612ec951b3ce4fa5954fd90
Author: Bastien Nocera <hadess hadess net>
Date: Fri Dec 8 13:21:06 2017 +0100
tests: Check locations against METAR database
Check whether all our airports/METAR stations:
- exist in the METAR database
- have a weather station
- and whether that station isn't obsolete
libgweather/test_libgweather.c | 130 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 130 insertions(+), 0 deletions(-)
---
diff --git a/libgweather/test_libgweather.c b/libgweather/test_libgweather.c
index b189d81..9d04e6d 100644
--- a/libgweather/test_libgweather.c
+++ b/libgweather/test_libgweather.c
@@ -20,9 +20,15 @@
#include "config.h"
#include <locale.h>
+#include <string.h>
+#include <libsoup/soup.h>
+
#include <gweather-version.h>
#include "gweather-location.h"
+/* For test_metar_weather_stations */
+#define METAR_SOURCES "https://www.aviationweather.gov/docs/metar/stations.txt"
+
/* Maximum for test_airport_distance_sanity() */
#define TOO_FAR 100.0
static double max_distance = 0.0;
@@ -159,6 +165,129 @@ test_airport_distance_sanity (void)
g_warning ("Maximum city to airport distance is %.1f km", max_distance);
}
+static GHashTable *
+parse_metar_stations (const char *contents)
+{
+ GHashTable *stations_ht;
+ char **lines;
+ guint i, num_stations;
+
+ stations_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ lines = g_strsplit (contents, "\n", -1);
+
+ for (i = 0; lines[i] != NULL; i++) {
+ char *line = lines[i];
+ char *station;
+
+ if (line[0] == '!')
+ continue;
+
+ if (strlen (line) != 83)
+ continue;
+
+ station = g_strndup (line + 20, 4);
+ /* Skip stations with no ICAO code */
+ if (g_str_equal (station, " ")) {
+ g_free (station);
+ continue;
+ }
+
+ if (g_hash_table_lookup (stations_ht, station)) {
+ if (g_str_equal (station, "VOGO") ||
+ g_str_equal (station, "KHQG")) {
+ g_free (station);
+ continue;
+ }
+ g_test_message ("Weather station '%s' already defined", station);
+ }
+
+ g_hash_table_insert (stations_ht, station, g_strdup (line));
+ num_stations++;
+ }
+
+ g_strfreev (lines);
+
+ /* Duplicates? */
+ g_assert_cmpuint (num_stations, ==, g_hash_table_size (stations_ht));
+
+ g_test_message ("Parsed %u weather stations", num_stations);
+
+ return stations_ht;
+}
+
+static void
+test_metar_weather_station (GWeatherLocation *location,
+ GHashTable *stations_ht)
+{
+ const char *code, *line;
+
+ code = gweather_location_get_code (location);
+ g_assert_nonnull (code);
+
+ line = g_hash_table_lookup (stations_ht, code);
+ if (!line) {
+ g_test_message ("Could not find airport for '%s'", code);
+ g_test_fail ();
+ } else {
+ char *has_metar;
+
+ has_metar = g_strndup (line + 62, 1);
+ if (*has_metar == 'Z') {
+ g_test_message ("Airport weather station '%s' is obsolete", code);
+ g_test_fail ();
+ } else if (*has_metar == ' ') {
+ g_test_message ("Could not find weather station for '%s'", code);
+ g_test_fail ();
+ }
+ g_free (has_metar);
+ }
+}
+
+static void
+test_metar_weather_stations_children (GWeatherLocation *location,
+ GHashTable *stations_ht)
+{
+ GWeatherLocation **children;
+ guint i;
+
+ children = gweather_location_get_children (location);
+ for (i = 0; children[i] != NULL; i++) {
+ if (gweather_location_get_level (children[i]) == GWEATHER_LOCATION_WEATHER_STATION)
+ test_metar_weather_station (children[i], stations_ht);
+ else
+ test_metar_weather_stations_children (children[i], stations_ht);
+ }
+}
+
+static void
+test_metar_weather_stations (void)
+{
+ GWeatherLocation *world;
+ SoupMessage *msg;
+ SoupSession *session;
+ GHashTable *stations_ht;
+ char *contents;
+
+ world = gweather_location_get_world ();
+ g_assert (world);
+
+ msg = soup_message_new ("GET", METAR_SOURCES);
+ session = soup_session_new ();
+ soup_session_send_message (session, msg);
+ g_assert (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code));
+ g_object_unref (session);
+ g_assert_nonnull (msg->response_body);
+
+ contents = g_strndup (msg->response_body->data, msg->response_body->length);
+ g_object_unref (msg);
+
+ stations_ht = parse_metar_stations (contents);
+ g_assert_nonnull (stations_ht);
+ g_free (contents);
+
+ test_metar_weather_stations_children (world, stations_ht);
+}
+
static void
log_handler (const char *log_domain, GLogLevelFlags log_level, const char *message, gpointer user_data)
{
@@ -183,6 +312,7 @@ main (int argc, char *argv[])
g_test_add_func ("/weather/named-timezones", test_named_timezones);
g_test_add_func ("/weather/timezones", test_timezones);
g_test_add_func ("/weather/airport_distance_sanity", test_airport_distance_sanity);
+ g_test_add_func ("/weather/metar_weather_stations", test_metar_weather_stations);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]