<commit_before>/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * Authors:
 *    <NAME> <<EMAIL>>
 */


#include "calendar/e-cal-backend-ews-utils.h"
#include "server/e-ews-connection.h"
#include "server/e-ews-debug.h"

#include "ews-test-common.h"

void (* populate_windows_zones) (void);
const gchar * (* ical_to_msdn_equivalent) (const gchar *);
void (* convert_calcomp_to_xml) (ESoapMessage *, gpointer);

const gchar *str_comp =
	"BEGIN:VEVENT\n"
	"UID:20140114T172626Z-2238-1000-5564-0@srv\n"
	"DTSTAMP:20140114T172620Z\n"
	"DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/ICAL_TIMEZONE:\n"
	" 20140114T160000\n"
	"DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/ICAL_TIMEZONE:\n"
	" 20140114T163000\n"
	"TRANSP:OPAQUE\n"
	"SEQUENCE:2\n"
	"SUMMARY:Test\n"
	"CLASS:PUBLIC\n"
	"ORGANIZER;CN=Someone:MAILTO:<EMAIL>\n"
	"ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;\n"
	" RSVP=TRUE;CN=Someone;LANGUAGE=en:MAILTO:<EMAIL>\n"
	"END:VEVENT";

static icalarray *builtin_timezones = NULL;

static void
server_notify_resolver_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
{
	UhmServer *local_server;
	UhmResolver *resolver;
	EwsTestData *etd;
	const gchar *hostname;

	local_server = UHM_SERVER (object);
	etd = user_data;
	hostname = etd->hostname;

	/* Set up the expected domain names here. This should technically be split up between
	 * the different unit test suites, but that's too much effort. */
	resolver = uhm_server_get_resolver (local_server);

	if (resolver != NULL) {
		const gchar *ip_address = uhm_server_get_address (local_server);

		uhm_resolver_add_A (resolver, hostname, ip_address);
	}
}

static void
test_libical_timezones_compatibility (gconstpointer user_data)
{
	gboolean retval = TRUE;
	gint i;

	for (i = 0; i < builtin_timezones->num_elements; i++) {
		icaltimezone *zone;
		const gchar *zone_location;

		zone = icalarray_element_at (builtin_timezones, i);
		zone_location = icaltimezone_get_location (zone);

		if (ical_to_msdn_equivalent (zone_location) == NULL) {
			retval = FALSE;
			g_printerr ("\nMissing ical_tz_location: %s\n", zone_location);
		}
	}

	g_assert (retval == TRUE);
}

static void
test_time_zones_sync (gconstpointer user_data)
{
	gboolean retval = FALSE;
	gint i;
	GError *error = NULL;
	UhmServer *local_server;
	EwsTestData *etd = (gpointer) user_data;
	EwsCalendarConvertData convert_data;
	EwsFolderId *calendar_fid;
	gboolean includes_last_folder = FALSE;
	gchar *old_sync_state = NULL;
	gchar **tokens;
	GSList *zone_location_errors = NULL;

	local_server = ews_test_get_mock_server ();

	ews_test_server_set_trace_directory (local_server, etd->version, "calendar/timezones");
	ews_test_server_start_trace (local_server, etd, "get_server_time_zones_sync", &error);
	if (error != NULL) {
		g_printerr ("\n%s\n", error->message);
		goto exit;
	}

	while (!includes_last_folder) {
		GSList *folders_created = NULL;
		GSList *folders_updated = NULL;
		GSList *folders_deleted = NULL;
		GSList *l;
		gchar *new_sync_state = NULL;
		gboolean found = FALSE;

		old_sync_state = new_sync_state;

		e_ews_connection_sync_folder_hierarchy_sync (
			etd->connection,
			EWS_PRIORITY_MEDIUM,
			old_sync_state,
			&new_sync_state,
			&includes_last_folder,
			&folders_created,
			&folders_updated,
			&folders_deleted,
			NULL,
			&error);

		if (error != NULL) {
			g_free (old_sync_state);
			g_printerr ("\n%s\n", error->message);
			goto exit;
		}

		for (l = folders_created; l != NULL; l = l->next) {
			EEwsFolder *folder = l->data;

			if (e_ews_folder_get_folder_type (folder) == E_EWS_FOLDER_TYPE_CALENDAR) {
				const EwsFolderId *fid;

				fid = e_ews_folder_get_id (folder);

				calendar_fid = g_new0 (EwsFolderId, 1);
				calendar_fid->id = g_strdup (fid->id);
				calendar_fid->change_key = g_strdup (fid->change_key);

				found = TRUE;
				break;
			}
		}

		g_slist_free_full (folders_created, g_object_unref);
		g_slist_free_full (folders_updated, g_object_unref);
		g_slist_free_full (folders_deleted, g_free);

		g_free (old_sync_state);
		old_sync_state = NULL;

		if (found) {
			g_free (new_sync_state);
			break;
		}
	}

	convert_data.connection = etd->connection;
	convert_data.default_zone = icaltimezone_get_utc_timezone ();

	tokens = g_strsplit (str_comp, "ICAL_TIMEZONE", 0);

	for (i = 0; i < builtin_timezones->num_elements; i++) {
		GSList *ll;
		GSList *ids = NULL;
		icaltimezone *zone;
		ECalComponent *comp;
		const gchar *zone_location;
		gchar *str;

		zone = icalarray_element_at (builtin_timezones, i);
		zone_location = icaltimezone_get_location (zone);

		str = g_strdup_printf ("%s%s%s%s%s", tokens[0], zone_location, tokens[1], zone_location, tokens[2]);
		comp = e_cal_component_new_from_string (str);
		g_free (str);

		convert_data.icalcomp = e_cal_component_get_icalcomponent (comp);

		e_ews_connection_create_items_sync (
			etd->connection,
			EWS_PRIORITY_MEDIUM,
			"SaveOnly",
			"SendToNone",
			calendar_fid,
			convert_calcomp_to_xml,
			&convert_data,
			&ids,
			NULL,<commit_msg>tests: Create a list of known unknown zones<commit_after>/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * Authors:
 *    <NAME> <<EMAIL>>
 */


#include "calendar/e-cal-backend-ews-utils.h"
#include "server/e-ews-connection.h"
#include "server/e-ews-debug.h"

#include "ews-test-common.h"

void (* populate_windows_zones) (void);
const gchar * (* ical_to_msdn_equivalent) (const gchar *);
void (* convert_calcomp_to_xml) (ESoapMessage *, gpointer);

const gchar *str_comp =
	"BEGIN:VEVENT\n"
	"UID:20140114T172626Z-2238-1000-5564-0@srv\n"
	"DTSTAMP:20140114T172620Z\n"
	"DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/ICAL_TIMEZONE:\n"
	" 20140114T160000\n"
	"DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/ICAL_TIMEZONE:\n"
	" 20140114T163000\n"
	"TRANSP:OPAQUE\n"
	"SEQUENCE:2\n"
	"SUMMARY:Test\n"
	"CLASS:PUBLIC\n"
	"ORGANIZER;CN=Someone:MAILTO:<EMAIL>\n"
	"ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;\n"
	" RSVP=TRUE;CN=Someone;LANGUAGE=en:MAILTO:<EMAIL>\n"
	"END:VEVENT";

/*
 * These timezones, present in tzdata, don't have a correspondent "Windows timezone".
 * In runtime, we fallback and set the server version as 2007_SP1 in the request, which
 * doesn't treat the transitions on the server side.
 * For tests purposes, this list of known unknown timezones is enough.
 */
static const gchar *unknown_timezones[] = {
	"Australia/Lord_Howe",
	"Australia/Eucla",
	"America/Atikokan",
	"Pacific/Easter",
	"Africa/Asmara",
	"Pacific/Chuuk",
	"Pacific/Pohnpei",
	"Atlantic/Faroe",
	"Pacific/Kiritimati",
	"Pacific/Norfolk",
	"Pacific/Chatham",
	"Pacific/Marquesas",
	"Pacific/Gambier",
	"America/Miquelon",
	"Pacific/Pitcairn",
	"Asia/Gaza",
	"Asia/Hebron",
	"America/Adak",
	"America/Metlakatla",
	"Asia/Ho_Chi_Minh",
	NULL
};

static icalarray *builtin_timezones = NULL;

static gboolean
is_a_known_unknown_timezone (const gchar *zone)
{
	gint i;

	for (i = 0; unknown_timezones[i] != NULL; i++) {
		if (g_strcmp0 (zone, unknown_timezones[i]) == 0)
			return TRUE;
	}

	return FALSE;
}

static void
server_notify_resolver_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
{
	UhmServer *local_server;
	UhmResolver *resolver;
	EwsTestData *etd;
	const gchar *hostname;

	local_server = UHM_SERVER (object);
	etd = user_data;
	hostname = etd->hostname;

	/* Set up the expected domain names here. This should technically be split up between
	 * the different unit test suites, but that's too much effort. */
	resolver = uhm_server_get_resolver (local_server);

	if (resolver != NULL) {
		const gchar *ip_address = uhm_server_get_address (local_server);

		uhm_resolver_add_A (resolver, hostname, ip_address);
	}
}

static void
test_libical_timezones_compatibility (gconstpointer user_data)
{
	gboolean retval = TRUE;
	gint i;

	for (i = 0; i < builtin_timezones->num_elements; i++) {
		icaltimezone *zone;
		const gchar *zone_location;

		zone = icalarray_element_at (builtin_timezones, i);
		zone_location = icaltimezone_get_location (zone);

		if (ical_to_msdn_equivalent (zone_location) == NULL) {
			if (!is_a_known_unknown_timezone (zone_location)) {
				retval = FALSE;
				g_printerr ("\nMissing ical_tz_location: %s\n", zone_location);
			}
		}
	}

	g_assert (retval == TRUE);
}

static void
test_time_zones_sync (gconstpointer user_data)
{
	gboolean retval = FALSE;
	gint i;
	GError *error = NULL;
	UhmServer *local_server;
	EwsTestData *etd = (gpointer) user_data;
	EwsCalendarConvertData convert_data;
	EwsFolderId *calendar_fid;
	gboolean includes_last_folder = FALSE;
	gchar *old_sync_state = NULL;
	gchar **tokens;
	GSList *zone_location_errors = NULL;

	local_server = ews_test_get_mock_server ();

	ews_test_server_set_trace_directory (local_server, etd->version, "calendar/timezones");
	ews_test_server_start_trace (local_server, etd, "get_server_time_zones_sync", &error);
	if (error != NULL) {
		g_printerr ("\n%s\n", error->message);
		goto exit;
	}

	while (!includes_last_folder) {
		GSList *folders_created = NULL;
		GSList *folders_updated = NULL;
		GSList *folders_deleted = NULL;
		GSList *l;
		gchar *new_sync_state = NULL;
		gboolean found = FALSE;

		old_sync_state = new_sync_state;

		e_ews_connection_sync_folder_hierarchy_sync (
			etd->connection,
			EWS_PRIORITY_MEDIUM,
			old_sync_state,
			&new_sync_state,
			&includes_last_folder,
			&folders_created,
			&folders_updated,
			&folders_deleted,
			NULL,
			&error);

		if (error != NULL) {
			g_free (old_sync_state);
			g_printerr ("\n%s\n", error->message);
			goto exit;
		}

		for (l = folders_created; l != NULL; l = l->next) {
			EEwsFolder *folder = l->data;

			if (e_ews_folder_get_folder_type (folder) == E_EWS_FOLDER_TYPE_CALENDAR) {
				const EwsFolderId *fid;

				fid = e_ews_folder_get_id (folder);

				calendar_fid = g_new0 (EwsFolderId, 1);
				calendar_fid->id = g_strdup (fid->id);
				calendar_fid->change_key = g_strdup (fid->change_key);

				found = TRUE;
				break;
			}
		}

		g_slist_free_full (folders_created, g_object_unref);
		g_slist_free_full (folders_updated, g_object_unref);
		g_slist_free_full (folders_deleted, g_free);

		g_free (old_sync_state);
		old_sync_state = NULL;

		if (found) {
			g_free (new_sync_state);
			break;
		}
	}

	convert_data.connection = etd->connection;
	convert_data.default_zone = icaltimezone_get_utc_timezone ();

	tokens = g_strsplit (str_comp, "ICAL_TIMEZONE", 0);

	for (i = 0; i < builtin_timezones->num_elements; i++) {
		GSList *ll;
		GSList *ids = NULL;
		icaltimezone *zone;
		ECalComponent *comp;
		const gchar *zone_location;
		gchar *str;

		zone = icalarray_element_at (builtin_timezones, i);
		zone_location = icaltimezone_get_location (zone);

		if (is_a_known_unknown_timezone (zone_location))
			continue;

		str = g_strdup_printf ("%s%s%s%s%s", tokens[0], zone_location, tokens[1], zone_location, tokens[2]);
		comp = e_cal_component_new_from_string (str);
		g_free (str);

		convert_data.icalcomp = e_cal_component_get_icalcomponent (comp);

		e_ews_connection_create_items_sync (
			etd->connection,
			EWS_PRIORITY_MEDIUM,
			"SaveOnly",
			"SendToNone",
			calendar_fid,
			convert_calcomp_to_xml,
			&convert_data,
			&ids,
			NULL,
{'fraction_non_alphanumeric': 0.1133954384837777, 'fraction_numerical': 0.015097976228718278, 'mean_word_length': 4.802889095992544, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4410294', 'n_tokens_mistral': 5215, 'n_tokens_neox': 4720, 'n_words': 1036}