[evolution-data-server/wip/offline-cache] Add a test for search expressions of ECalCache
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/offline-cache] Add a test for search expressions of ECalCache
- Date: Tue, 21 Mar 2017 17:32:29 +0000 (UTC)
commit ae5bebefcbd3e7d25ecfc003e2dc4e7fb973d65e
Author: Milan Crha <mcrha redhat com>
Date: Tue Feb 21 22:34:56 2017 +0100
Add a test for search expressions of ECalCache
src/calendar/libedata-cal/e-cal-backend-sexp.c | 28 +-
src/calendar/libedata-cal/e-cal-cache.c | 284 ++++++++++-----
tests/libedata-cal/CMakeLists.txt | 1 +
tests/libedata-cal/components/event-2.ics | 2 +
tests/libedata-cal/components/event-3.ics | 1 +
tests/libedata-cal/components/event-4.ics | 2 +
tests/libedata-cal/components/event-6-a.ics | 13 +
tests/libedata-cal/components/event-6.ics | 12 +
tests/libedata-cal/components/event-7.ics | 13 +
tests/libedata-cal/components/event-8.ics | 16 +
tests/libedata-cal/components/event-9.ics | 17 +
tests/libedata-cal/components/task-1.ics | 9 +
tests/libedata-cal/components/task-2.ics | 11 +
tests/libedata-cal/components/task-3.ics | 13 +
tests/libedata-cal/components/task-4.ics | 13 +
tests/libedata-cal/components/task-5.ics | 13 +
tests/libedata-cal/components/task-6.ics | 14 +
tests/libedata-cal/components/task-7.ics | 17 +
tests/libedata-cal/components/task-8.ics | 11 +
tests/libedata-cal/components/task-9.ics | 11 +
tests/libedata-cal/test-cal-cache-intervals.c | 35 ++-
tests/libedata-cal/test-cal-cache-offline.c | 2 +-
tests/libedata-cal/test-cal-cache-search.c | 470 ++++++++++++++++++++++++
tests/libedata-cal/test-cal-cache-utils.c | 27 ++-
tests/libedata-cal/test-cal-cache-utils.h | 8 +-
25 files changed, 936 insertions(+), 107 deletions(-)
---
diff --git a/src/calendar/libedata-cal/e-cal-backend-sexp.c b/src/calendar/libedata-cal/e-cal-backend-sexp.c
index c2c96fe..466d9d2 100644
--- a/src/calendar/libedata-cal/e-cal-backend-sexp.c
+++ b/src/calendar/libedata-cal/e-cal-backend-sexp.c
@@ -536,23 +536,24 @@ matches_any (ECalComponent *comp,
static gboolean
matches_priority (ECalComponent *comp ,const gchar *pr)
{
+ gboolean res = FALSE;
gint *priority = NULL;
e_cal_component_get_priority (comp, &priority);
- if (!priority || !*priority)
- return FALSE;
+ if (!priority)
+ return g_str_equal (pr, "UNDEFINED");
if (g_str_equal (pr, "HIGH") && *priority <= 4)
- return TRUE;
+ res = TRUE;
else if (g_str_equal (pr, "NORMAL") && *priority == 5)
- return TRUE;
+ res = TRUE;
else if (g_str_equal (pr, "LOW") && *priority > 5)
- return TRUE;
- else if (g_str_equal (pr, "UNDEFINED") && (!priority || !*priority))
- return TRUE;
+ res = TRUE;
- return FALSE;
+ e_cal_component_free_priority (priority);
+
+ return res;
}
static gboolean
@@ -638,10 +639,13 @@ func_percent_complete (ESExp *esexp,
e_cal_component_get_percent (ctx->comp, &percent);
- if (percent && *percent) {
- result = e_sexp_result_new (esexp, ESEXP_RES_INT);
- result->value.number = *percent;
+ result = e_sexp_result_new (esexp, ESEXP_RES_INT);
+ if (percent) {
+ result->value.number = *percent;
+ e_cal_component_free_percent (percent);
+ } else {
+ result->value.number = -1;
}
return result;
@@ -935,6 +939,8 @@ func_has_categories (ESExp *esexp,
result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
result->value.boolean = FALSE;
+ e_cal_component_free_categories_list (categories);
+
return result;
}
diff --git a/src/calendar/libedata-cal/e-cal-cache.c b/src/calendar/libedata-cal/e-cal-cache.c
index d6eecb2..eff7407 100644
--- a/src/calendar/libedata-cal/e-cal-cache.c
+++ b/src/calendar/libedata-cal/e-cal-cache.c
@@ -256,6 +256,21 @@ ecc_check_sexp_func (sqlite3_context *context,
g_object_unref (sexp_obj);
}
+/* negate(x) */
+static void
+ecc_negate_func (sqlite3_context *context,
+ gint argc,
+ sqlite3_value **argv)
+{
+ gint val;
+
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (argc == 1);
+
+ val = sqlite3_value_int (argv[0]);
+ sqlite3_result_int (context, !val);
+}
+
static gboolean
e_cal_cache_get_string (ECache *cache,
gint ncols,
@@ -362,7 +377,7 @@ ecc_decode_id_sql (const gchar *id,
if (!*id)
return FALSE;
- split = g_strsplit (id, "\n", 1);
+ split = g_strsplit (id, "\n", 2);
if (!split || !split[0] || !*split[0]) {
g_strfreev (split);
@@ -655,29 +670,29 @@ ecc_get_status_as_string (icalproperty_status status)
{
switch (status) {
case ICAL_STATUS_NONE:
- return "NOT STARTED";
+ return "not started";
case ICAL_STATUS_COMPLETED:
- return "COMPLETED";
+ return "completed";
case ICAL_STATUS_CANCELLED:
- return "CANCELLED";
+ return "cancelled";
case ICAL_STATUS_INPROCESS:
- return "IN PROGRESS";
+ return "in progress";
case ICAL_STATUS_NEEDSACTION:
- return "NEEDS ACTION";
+ return "needs action";
case ICAL_STATUS_TENTATIVE:
- return "TENTATIVE";
+ return "tentative";
case ICAL_STATUS_CONFIRMED:
- return "CONFIRMED";
+ return "confirmed";
case ICAL_STATUS_DRAFT:
- return "DRAFT";
+ return "draft";
case ICAL_STATUS_FINAL:
- return "FINAL";
+ return "final";
case ICAL_STATUS_SUBMITTED:
- return "SUBMITTED";
+ return "submitted";
case ICAL_STATUS_PENDING:
- return "PENDING";
+ return "pending";
case ICAL_STATUS_FAILED:
- return "FAILED";
+ return "failed";
case ICAL_STATUS_X:
break;
}
@@ -693,9 +708,9 @@ ecc_fill_other_columns (ECalCache *cal_cache,
time_t occur_start = -1, occur_end = -1;
ECalComponentDateTime dt;
ECalComponentText text;
- ECalComponentClassification classification;
+ ECalComponentClassification classification = E_CAL_COMPONENT_CLASS_PUBLIC;
icalcomponent *icalcomp;
- icalproperty_status status;
+ icalproperty_status status = ICAL_STATUS_NONE;
struct icaltimetype *itt;
const gchar *str = NULL;
gint *pint = NULL;
@@ -724,6 +739,8 @@ ecc_fill_other_columns (ECalCache *cal_cache,
itt = NULL;
e_cal_component_get_completed (comp, &itt);
add_value (ECC_COLUMN_COMPLETED, itt ? ecc_encode_itt_to_sql (*itt) : NULL);
+ if (itt)
+ e_cal_component_free_icaltimetype (itt);
text.value = NULL;
e_cal_component_get_summary (comp, &text);
@@ -740,15 +757,19 @@ ecc_fill_other_columns (ECalCache *cal_cache,
e_cal_component_get_priority (comp, &pint);
add_value (ECC_COLUMN_PRIORITY, pint && *pint ? g_strdup_printf ("%d", *pint) : NULL);
+ if (pint)
+ e_cal_component_free_priority (pint);
e_cal_component_get_percent (comp, &pint);
add_value (ECC_COLUMN_PERCENT_COMPLETE, pint && *pint ? g_strdup_printf ("%d", *pint) : NULL);
+ if (pint)
+ e_cal_component_free_percent (pint);
has = e_cal_component_has_alarms (comp);
add_value (ECC_COLUMN_HAS_ALARM, g_strdup (has ? "1" : "0"));
has = e_cal_component_has_attachments (comp);
- add_value (ECC_COLUMN_HAS_ALARM, g_strdup (has ? "1" : "0"));
+ add_value (ECC_COLUMN_HAS_ATTACHMENT, g_strdup (has ? "1" : "0"));
e_cal_component_get_dtstart (comp, &dt);
has = dt.value != NULL;
@@ -775,7 +796,7 @@ ecc_range_as_where_clause (const gchar *start_str,
if (!start_str && !end_str)
return NULL;
- stmt = g_string_new ("");
+ stmt = g_string_sized_new (64);
if (start_str) {
e_cache_sqlite_stmt_append_printf (stmt,
@@ -802,7 +823,8 @@ ecc_range_as_where_clause (const gchar *start_str,
typedef struct _SExpToSqlContext {
ECalCache *cal_cache;
- gint sexp_id;
+ guint not_level;
+ gboolean requires_check_sexp;
} SExpToSqlContext;
static ESExpResult *
@@ -824,20 +846,19 @@ ecc_sexp_func_and_or (ESExp *esexp,
for (ii = 0; ii < argc; ii++) {
r1 = e_sexp_term_eval (esexp, argv[ii]);
- if (stmt->len > 1)
- g_string_append_printf (stmt, " %s ", oper);
+ if (r1 && r1->type == ESEXP_RES_STRING && r1->value.string) {
+ if (stmt->len > 1)
+ g_string_append_printf (stmt, " %s ", oper);
- if (r1 && r1->type == ESEXP_RES_STRING) {
g_string_append_printf (stmt, "(%s)", r1->value.string);
} else {
- g_string_append_printf (stmt, "check_sexp(%d,%s)",
- ctx->sexp_id, E_CACHE_COLUMN_OBJECT);
+ ctx->requires_check_sexp = TRUE;
}
e_sexp_result_free (esexp, r1);
}
- if (stmt->len == 1) {
+ if (stmt->len == 1 && !ctx->not_level) {
if (g_str_equal (oper, "AND"))
g_string_append_c (stmt, '1');
else
@@ -847,7 +868,7 @@ ecc_sexp_func_and_or (ESExp *esexp,
g_string_append_c (stmt, ')');
result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
- result->value.string = g_string_free (stmt, FALSE);
+ result->value.string = g_string_free (stmt, stmt->len <= 2);
return result;
}
@@ -873,11 +894,11 @@ ecc_sexp_func_or (ESExp *esexp,
static ESExpResult *
ecc_sexp_func_not (ESExp *esexp,
gint argc,
- ESExpResult **argv,
+ ESExpTerm **argv,
gpointer user_data)
{
SExpToSqlContext *ctx = user_data;
- ESExpResult *result;
+ ESExpResult *result, *r1;
g_return_val_if_fail (ctx != NULL, NULL);
@@ -886,15 +907,20 @@ ecc_sexp_func_not (ESExp *esexp,
result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
- if (!argv[0] || argv[0]->type != ESEXP_RES_STRING) {
- result->value.string =
- g_strdup_printf ("check_sexp(%d,%s)",
- ctx->sexp_id,
- E_CACHE_COLUMN_OBJECT);
+ ctx->not_level++;
+
+ r1 = e_sexp_term_eval (esexp, argv[0]);
+
+ ctx->not_level--;
+
+ if (r1 && r1->type == ESEXP_RES_STRING && r1->value.string) {
+ result->value.string = g_strdup_printf ("negate(%s)", r1->value.string);
} else {
- result->value.string = g_strdup_printf ("NOT (%s)", argv[0]->value.string);
+ ctx->requires_check_sexp = TRUE;
}
+ e_sexp_result_free (esexp, r1);
+
return result;
}
@@ -942,9 +968,6 @@ ecc_sexp_func_occur_in_time_range (ESExp *esexp,
{
SExpToSqlContext *ctx = user_data;
ESExpResult *result;
- icaltimezone *default_zone = NULL;
- struct icaltimetype itt_start, itt_end;
- gchar *start_str, *end_str;
g_return_val_if_fail (ctx != NULL, NULL);
@@ -955,23 +978,31 @@ ecc_sexp_func_occur_in_time_range (ESExp *esexp,
return NULL;
}
- if (argc == 3)
- default_zone = ecc_resolve_tzid_cb (argv[2]->value.string, ctx->cal_cache);
+ result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
- itt_start = icaltime_from_timet_with_zone (argv[0]->value.time, 0, default_zone);
- itt_end = icaltime_from_timet_with_zone (argv[1]->value.time, 0, default_zone);
+ if (!ctx->not_level) {
+ struct icaltimetype itt_start, itt_end;
+ gchar *start_str, *end_str;
- start_str = ecc_encode_itt_to_sql (itt_start);
- end_str = ecc_encode_itt_to_sql (itt_end);
+ /* The default zone argument, if any, is ignored here */
+ itt_start = icaltime_from_timet_with_zone (argv[0]->value.time, 0, NULL);
+ itt_end = icaltime_from_timet_with_zone (argv[1]->value.time, 0, NULL);
- result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
- result->value.string = ecc_range_as_where_clause (start_str, end_str);
+ start_str = ecc_encode_itt_to_sql (itt_start);
+ end_str = ecc_encode_itt_to_sql (itt_end);
- if (!result->value.string)
- result->value.string = g_strdup ("1==1");
+ result->value.string = ecc_range_as_where_clause (start_str, end_str);
- g_free (start_str);
- g_free (end_str);
+ if (!result->value.string)
+ result->value.string = g_strdup ("1=1");
+
+ g_free (start_str);
+ g_free (end_str);
+ } else {
+ result->value.string = NULL;
+ }
+
+ ctx->requires_check_sexp = TRUE;
return result;
}
@@ -1057,7 +1088,23 @@ ecc_sexp_func_contains (ESExp *esexp,
} else if (column) {
gchar *stmt;
- stmt = e_cache_sqlite_stmt_printf ("%s LIKE '%%%q%%'", column, str);
+ if (g_str_equal (column, ECC_COLUMN_PRIORITY)) {
+ if (g_ascii_strcasecmp (str, "UNDEFINED") == 0)
+ stmt = e_cache_sqlite_stmt_printf ("%s IS NULL", column);
+ else if (g_ascii_strcasecmp (str, "HIGH") == 0)
+ stmt = e_cache_sqlite_stmt_printf ("%s<=4", column);
+ else if (g_ascii_strcasecmp (str, "NORMAL") == 0)
+ stmt = e_cache_sqlite_stmt_printf ("%s=5", column);
+ else if (g_ascii_strcasecmp (str, "LOW") == 0)
+ stmt = e_cache_sqlite_stmt_printf ("%s>5", column);
+ else
+ stmt = e_cache_sqlite_stmt_printf ("%s IS NOT NULL", column);
+ } else if (g_str_equal (column, ECC_COLUMN_CLASSIFICATION) ||
+ g_str_equal (column, ECC_COLUMN_STATUS)) {
+ stmt = e_cache_sqlite_stmt_printf ("%s='%q'", column, str);
+ } else {
+ stmt = e_cache_sqlite_stmt_printf ("%s LIKE '%%%q%%'", column, str);
+ }
result->value.string = g_strdup (stmt);
e_cache_sqlite_stmt_free (stmt);
} else if (g_str_equal (field, "any")) {
@@ -1072,9 +1119,7 @@ ecc_sexp_func_contains (ESExp *esexp,
result->value.string = g_string_free (stmt, FALSE);
} else {
- g_strdup_printf ("check_sexp(%d,%s)",
- ctx->sexp_id,
- E_CACHE_COLUMN_OBJECT);
+ ctx->requires_check_sexp = TRUE;
}
g_free (str);
@@ -1119,6 +1164,28 @@ ecc_sexp_func_has_alarms (ESExp *esexp,
}
static ESExpResult *
+ecc_sexp_func_has_alarms_in_range (ESExp *esexp,
+ gint argc,
+ ESExpResult **argv,
+ gpointer user_data)
+{
+ SExpToSqlContext *ctx = user_data;
+ ESExpResult *result;
+
+ g_return_val_if_fail (ctx != NULL, NULL);
+
+ ctx->requires_check_sexp = TRUE;
+
+ if (!ctx->not_level)
+ return ecc_sexp_func_has_alarms (esexp, argc, argv, user_data);
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
+ result->value.string = NULL;
+
+ return result;
+}
+
+static ESExpResult *
ecc_sexp_func_has_recurrences (ESExp *esexp,
gint argc,
ESExpResult **argv,
@@ -1280,10 +1347,9 @@ ecc_sexp_func_check_sexp (ESExp *esexp,
g_return_val_if_fail (ctx != NULL, NULL);
result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
- result->value.string =
- g_strdup_printf ("check_sexp(%d,%s)",
- ctx->sexp_id,
- E_CACHE_COLUMN_OBJECT);
+ result->value.string = NULL;
+
+ ctx->requires_check_sexp = TRUE;
return result;
}
@@ -1300,10 +1366,9 @@ ecc_sexp_func_icheck_sexp (ESExp *esexp,
g_return_val_if_fail (ctx != NULL, NULL);
result = e_sexp_result_new (esexp, ESEXP_RES_STRING);
- result->value.string =
- g_strdup_printf ("check_sexp(%d,%s)",
- ctx->sexp_id,
- E_CACHE_COLUMN_OBJECT);
+ result->value.string = NULL;
+
+ ctx->requires_check_sexp = TRUE;
return result;
}
@@ -1315,7 +1380,7 @@ static struct {
} symbols[] = {
{ "and", ecc_sexp_func_and, 1 },
{ "or", ecc_sexp_func_or, 1 },
- { "not", ecc_sexp_func_not, 0 },
+ { "not", ecc_sexp_func_not, 1 },
{ "<", ecc_sexp_func_icheck_sexp, 1 },
{ ">", ecc_sexp_func_icheck_sexp, 1 },
{ "=", ecc_sexp_func_icheck_sexp, 1 },
@@ -1340,7 +1405,7 @@ static struct {
{ "contains?", ecc_sexp_func_contains, 0 },
{ "has-start?", ecc_sexp_func_has_start, 0 },
{ "has-alarms?", ecc_sexp_func_has_alarms, 0 },
- { "has-alarms-in-range?", ecc_sexp_func_check_sexp, 0 },
+ { "has-alarms-in-range?", ecc_sexp_func_has_alarms_in_range, 0 },
{ "has-recurrences?", ecc_sexp_func_has_recurrences, 0 },
{ "has-categories?", ecc_sexp_func_has_categories, 0 },
{ "is-completed?", ecc_sexp_func_is_completed, 0 },
@@ -1372,7 +1437,8 @@ ecc_convert_sexp_to_sql (ECalCache *cal_cache,
return TRUE;
ctx.cal_cache = cal_cache;
- ctx.sexp_id = sexp_id;
+ ctx.not_level = 0;
+ ctx.requires_check_sexp = FALSE;
sexp_parser = e_sexp_new ();
@@ -1394,9 +1460,19 @@ ecc_convert_sexp_to_sql (ECalCache *cal_cache,
if (result) {
if (result->type == ESEXP_RES_STRING) {
- /* Just steal the string from the ESexpResult */
- *out_where_clause = result->value.string;
- result->value.string = NULL;
+ if (ctx.requires_check_sexp) {
+ if (result->value.string) {
+ *out_where_clause = g_strdup_printf ("((%s) AND
check_sexp(%d,%s))",
+ result->value.string, sexp_id, E_CACHE_COLUMN_OBJECT);
+ } else {
+ *out_where_clause = g_strdup_printf ("check_sexp(%d,%s)",
+ sexp_id, E_CACHE_COLUMN_OBJECT);
+ }
+ } else {
+ /* Just steal the string from the ESExpResult */
+ *out_where_clause = result->value.string;
+ result->value.string = NULL;
+ }
success = TRUE;
}
}
@@ -1530,6 +1606,14 @@ ecc_init_sqlite_functions (ECalCache *cal_cache,
cal_cache, ecc_check_sexp_func,
NULL, NULL);
+ if (ret == SQLITE_OK) {
+ /* negate(x) */
+ ret = sqlite3_create_function (sqlitedb,
+ "negate", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
+ NULL, ecc_negate_func,
+ NULL, NULL);
+ }
+
if (ret != SQLITE_OK) {
const gchar *errmsg = sqlite3_errmsg (sqlitedb);
@@ -2267,6 +2351,26 @@ e_cal_cache_get_components_in_range (ECalCache *cal_cache,
return success;
}
+static gboolean
+ecc_search_icalstrings_cb (ECalCache *cal_cache,
+ const gchar *uid,
+ const gchar *rid,
+ const gchar *revision,
+ const gchar *object,
+ const gchar *extra,
+ EOfflineState offline_state,
+ gpointer user_data)
+{
+ GSList **out_icalstrings = user_data;
+
+ g_return_val_if_fail (out_icalstrings != NULL, FALSE);
+ g_return_val_if_fail (object != NULL, FALSE);
+
+ *out_icalstrings = g_slist_prepend (*out_icalstrings, g_strdup (object));
+
+ return TRUE;
+}
+
/**
* e_cal_cache_get_components_in_range_as_strings:
* @cal_cache: an #ECalCache
@@ -2290,8 +2394,8 @@ e_cal_cache_get_components_in_range_as_strings (ECalCache *cal_cache,
GCancellable *cancellable,
GError **error)
{
- GString *stmt;
- gchar *range_start_str, *range_end_str, *range_where_clause;
+ gchar *sexp;
+ struct icaltimetype itt_start, itt_end;
gboolean success;
g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
@@ -2299,26 +2403,24 @@ e_cal_cache_get_components_in_range_as_strings (ECalCache *cal_cache,
*out_icalstrings = NULL;
- range_start_str = ecc_encode_timet_to_sql (cal_cache, range_start);
- range_end_str = ecc_encode_timet_to_sql (cal_cache, range_end);
- range_where_clause = ecc_range_as_where_clause (range_start_str, range_end_str);
+ itt_start = icaltime_from_timet_with_zone (range_start, FALSE, NULL);
+ itt_end = icaltime_from_timet_with_zone (range_end, FALSE, NULL);
- /* Using 'ORDER BY' to get the master object first */
- stmt = g_string_new ("SELECT " E_CACHE_COLUMN_OBJECT " FROM " E_CACHE_TABLE_OBJECTS);
-
- if (range_where_clause) {
- g_string_append (stmt, " WHERE ");
- g_string_append (stmt, range_where_clause);
- }
+ sexp = g_strdup_printf ("(occur-in-time-range? (make-time \"%04d%02d%02dT%02d%02d%02dZ\") (make-time
\"%04d%02d%02dT%02d%02d%02dZ\"))",
+ itt_start.year, itt_start.month, itt_start.day, itt_start.hour, itt_start.minute,
itt_start.second,
+ itt_end.year, itt_end.month, itt_end.day, itt_end.hour, itt_end.minute, itt_end.second);
- g_string_append (stmt, " ORDER BY " E_CACHE_COLUMN_UID);
+ success = e_cal_cache_search_with_callback (cal_cache, sexp, ecc_search_icalstrings_cb,
+ out_icalstrings, cancellable, error);
- success = e_cache_sqlite_select (E_CACHE (cal_cache), stmt->str, e_cal_cache_get_strings,
out_icalstrings, cancellable, error);
+ g_free (sexp);
- g_string_free (stmt, TRUE);
- g_free (range_where_clause);
- g_free (range_start_str);
- g_free (range_end_str);
+ if (success) {
+ *out_icalstrings = g_slist_reverse (*out_icalstrings);
+ } else {
+ g_slist_free_full (*out_icalstrings, g_free);
+ *out_icalstrings = NULL;
+ }
return success;
}
@@ -3035,10 +3137,18 @@ ecc_get_cached_timezone (ETimezoneCache *cache,
/* See if we already have it in the cache. */
zone = g_hash_table_lookup (cal_cache->priv->loaded_timezones, tzid);
+ if (zone)
+ goto exit;
- if (zone != NULL)
+ zone = g_hash_table_lookup (cal_cache->priv->modified_timezones, tzid);
+ if (zone)
goto exit;
+ /* Try the location first */
+ /*zone = icaltimezone_get_builtin_timezone (tzid);
+ if (zone)
+ goto exit;*/
+
/* Try to replace the original time zone with a more complete
* and/or potentially updated built-in time zone. Note this also
* applies to TZIDs which match built-in time zones exactly: they
@@ -3046,10 +3156,10 @@ ecc_get_cached_timezone (ETimezoneCache *cache,
builtin_tzid = e_cal_match_tzid (tzid);
- if (builtin_tzid != NULL)
+ if (builtin_tzid)
builtin_zone = icaltimezone_get_builtin_timezone_from_tzid (builtin_tzid);
- if (builtin_zone == NULL) {
+ if (!builtin_zone) {
e_cal_cache_get_timezone (cal_cache, tzid, &zone, NULL, NULL);
goto exit;
}
diff --git a/tests/libedata-cal/CMakeLists.txt b/tests/libedata-cal/CMakeLists.txt
index eb70d3c..4f0b24e 100644
--- a/tests/libedata-cal/CMakeLists.txt
+++ b/tests/libedata-cal/CMakeLists.txt
@@ -80,6 +80,7 @@ set(TESTS
test-intervaltree
test-cal-cache-offline
test-cal-cache-intervals
+ test-cal-cache-search
)
foreach(_test ${TESTS})
diff --git a/tests/libedata-cal/components/event-2.ics b/tests/libedata-cal/components/event-2.ics
index 3b6efef..ce980be 100644
--- a/tests/libedata-cal/components/event-2.ics
+++ b/tests/libedata-cal/components/event-2.ics
@@ -9,4 +9,6 @@ DTEND:20170103T083000Z
SUMMARY:First working day
DESCRIPTION:Multiline\n
description text
+CLASS:CONFIDENTIAL
+CATEGORIES:Work,Hard
END:VEVENT
diff --git a/tests/libedata-cal/components/event-3.ics b/tests/libedata-cal/components/event-3.ics
index bbbaac5..4fcf5bf 100644
--- a/tests/libedata-cal/components/event-3.ics
+++ b/tests/libedata-cal/components/event-3.ics
@@ -8,4 +8,5 @@ DTSTART:20170104T100000Z
DTEND:20170110T120000Z
SUMMARY:Lunch prepare
LOCATION:Kitchen
+CLASS:PRIVATE
END:VEVENT
diff --git a/tests/libedata-cal/components/event-4.ics b/tests/libedata-cal/components/event-4.ics
index fd83a62..eb409ff 100644
--- a/tests/libedata-cal/components/event-4.ics
+++ b/tests/libedata-cal/components/event-4.ics
@@ -8,4 +8,6 @@ DTSTART:20170102T100000Z
DTEND:20170102T180000Z
SUMMARY:After-party clean up
LOCATION:All around
+CLASS:PUBLIC
+CATEGORIES:Holiday,Work
END:VEVENT
diff --git a/tests/libedata-cal/components/event-6-a.ics b/tests/libedata-cal/components/event-6-a.ics
new file mode 100644
index 0000000..404b51e
--- /dev/null
+++ b/tests/libedata-cal/components/event-6-a.ics
@@ -0,0 +1,13 @@
+BEGIN:VEVENT
+UID:event-6
+DTSTAMP:20170221T121736Z
+DTSTART;TZID=America/New_York:20170225T150000
+DTEND;TZID=America/New_York:20170225T160000
+SEQUENCE:2
+SUMMARY:Recurring with detached instance (3rd instance)
+TRANSP:OPAQUE
+CLASS:PUBLIC
+CREATED:20170221T125024Z
+LAST-MODIFIED:20170221T125341Z
+RECURRENCE-ID;TZID=America/New_York:20170225T134900
+END:VEVENT
diff --git a/tests/libedata-cal/components/event-6.ics b/tests/libedata-cal/components/event-6.ics
new file mode 100644
index 0000000..ee85a01
--- /dev/null
+++ b/tests/libedata-cal/components/event-6.ics
@@ -0,0 +1,12 @@
+BEGIN:VEVENT
+UID:event-6
+DTSTAMP:20170221T121736Z
+DTSTART;TZID=America/New_York:20170221T134900
+DTEND;TZID=America/New_York:20170221T144900
+SEQUENCE:1
+SUMMARY:Recurring with detached instance
+RRULE:FREQ=DAILY;COUNT=5;INTERVAL=2
+CLASS:PUBLIC
+CREATED:20170221T125024Z
+LAST-MODIFIED:20170221T125024Z
+END:VEVENT
diff --git a/tests/libedata-cal/components/event-7.ics b/tests/libedata-cal/components/event-7.ics
new file mode 100644
index 0000000..f1c0523
--- /dev/null
+++ b/tests/libedata-cal/components/event-7.ics
@@ -0,0 +1,13 @@
+BEGIN:VEVENT
+UID:event-7
+DTSTAMP:20170221T121736Z
+DTSTART;TZID=America/New_York:20170221T135000
+DTEND;TZID=America/New_York:20170221T145000
+SEQUENCE:1
+SUMMARY:With attachment
+TRANSP:OPAQUE
+ATTACH:file:///usr/share/icons/hicolor/48x48/apps/evolution.png
+CLASS:PUBLIC
+CREATED:20170221T125054Z
+LAST-MODIFIED:20170221T125054Z
+END:VEVENT
diff --git a/tests/libedata-cal/components/event-8.ics b/tests/libedata-cal/components/event-8.ics
new file mode 100644
index 0000000..89db909
--- /dev/null
+++ b/tests/libedata-cal/components/event-8.ics
@@ -0,0 +1,16 @@
+BEGIN:VEVENT
+UID:event-8
+DTSTAMP:20170221T121736Z
+DTSTART;TZID=America/New_York:20170225T160000
+DTEND;TZID=America/New_York:20170225T170000
+SEQUENCE:2
+ORGANIZER;CN=Bob:MAILTO:bob@no.where
+ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;
+ RSVP=TRUE;LANGUAGE=en:MAILTO:alice@no.where
+SUMMARY:Meet Alice
+COMMENT:User commentary text
+TRANSP:OPAQUE
+CLASS:PUBLIC
+CREATED:20170221T131322Z
+LAST-MODIFIED:20170221T131322Z
+END:VEVENT
diff --git a/tests/libedata-cal/components/event-9.ics b/tests/libedata-cal/components/event-9.ics
new file mode 100644
index 0000000..70b96f7
--- /dev/null
+++ b/tests/libedata-cal/components/event-9.ics
@@ -0,0 +1,17 @@
+BEGIN:VEVENT
+UID:event-9
+DTSTAMP:20170221T121736Z
+DTSTART;TZID=America/new_York:20170225T160000
+DTEND;TZID=America/new_York:20170225T170000
+SEQUENCE:2
+ORGANIZER;CN=Alice:MAILTO:alice@no.where
+ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;
+ RSVP=TRUE;CN=Bob;LANGUAGE=en:MAILTO:bob@no.where
+ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;
+ RSVP=TRUE;CN=Charlie;LANGUAGE=en:MAILTO:charlie@no.where
+SUMMARY:2-on-1
+TRANSP:OPAQUE
+CLASS:PUBLIC
+CREATED:20170221T131421Z
+LAST-MODIFIED:20170221T131421Z
+END:VEVENT
diff --git a/tests/libedata-cal/components/task-1.ics b/tests/libedata-cal/components/task-1.ics
new file mode 100644
index 0000000..f64663c
--- /dev/null
+++ b/tests/libedata-cal/components/task-1.ics
@@ -0,0 +1,9 @@
+BEGIN:VTODO
+UID:task-1
+DTSTAMP:20170221T130109Z
+SUMMARY:Simple task
+CLASS:PUBLIC
+SEQUENCE:1
+CREATED:20170221T130123Z
+LAST-MODIFIED:20170221T130123Z
+END:VTODO
diff --git a/tests/libedata-cal/components/task-2.ics b/tests/libedata-cal/components/task-2.ics
new file mode 100644
index 0000000..64b83ab
--- /dev/null
+++ b/tests/libedata-cal/components/task-2.ics
@@ -0,0 +1,11 @@
+BEGIN:VTODO
+UID:task-2
+DTSTAMP:20170221T130109Z
+SUMMARY:With Due date
+DUE;TZID=America/New_York:20170313T000000
+PERCENT-COMPLETE:0
+CLASS:PUBLIC
+SEQUENCE:1
+CREATED:20170221T130208Z
+LAST-MODIFIED:20170221T130208Z
+END:VTODO
diff --git a/tests/libedata-cal/components/task-3.ics b/tests/libedata-cal/components/task-3.ics
new file mode 100644
index 0000000..e54e4fc
--- /dev/null
+++ b/tests/libedata-cal/components/task-3.ics
@@ -0,0 +1,13 @@
+BEGIN:VTODO
+UID:task-3
+DTSTAMP:20170221T130109Z
+SUMMARY:With completed
+STATUS:COMPLETED
+COMPLETED;America/New_York:20170221T000000
+PERCENT-COMPLETE:100
+CLASS:PUBLIC
+DESCRIPTION:Task having _with_ in description
+SEQUENCE:1
+CREATED:20170221T130319Z
+LAST-MODIFIED:20170221T130319Z
+END:VTODO
diff --git a/tests/libedata-cal/components/task-4.ics b/tests/libedata-cal/components/task-4.ics
new file mode 100644
index 0000000..82c36aa
--- /dev/null
+++ b/tests/libedata-cal/components/task-4.ics
@@ -0,0 +1,13 @@
+BEGIN:VTODO
+UID:task-4
+DTSTAMP:20170221T130109Z
+SUMMARY:With completed (2nd) and Due
+STATUS:COMPLETED
+DUE;TZID=America/New_York:20170301T000000
+COMPLETED;TZID=America/New_York:20170221T000000
+PERCENT-COMPLETE:100
+CLASS:PUBLIC
+SEQUENCE:1
+CREATED:20170221T130339Z
+LAST-MODIFIED:20170221T130339Z
+END:VTODO
diff --git a/tests/libedata-cal/components/task-5.ics b/tests/libedata-cal/components/task-5.ics
new file mode 100644
index 0000000..b813194
--- /dev/null
+++ b/tests/libedata-cal/components/task-5.ics
@@ -0,0 +1,13 @@
+BEGIN:VTODO
+UID:task-5
+DTSTAMP:20170221T130109Z
+SUMMARY:20% complete
+STATUS:IN-PROCESS
+PERCENT-COMPLETE:20
+CLASS:PUBLIC
+SEQUENCE:1
+PRIORITY:7
+CREATED:20170221T130411Z
+LAST-MODIFIED:20170221T130411Z
+LOCATION:Kitchen
+END:VTODO
diff --git a/tests/libedata-cal/components/task-6.ics b/tests/libedata-cal/components/task-6.ics
new file mode 100644
index 0000000..1ea7777
--- /dev/null
+++ b/tests/libedata-cal/components/task-6.ics
@@ -0,0 +1,14 @@
+BEGIN:VTODO
+UID:task-6
+DTSTAMP:20170221T130109Z
+SUMMARY:90% complete (Confidential)
+STATUS:IN-PROCESS
+PRIORITY:5
+PERCENT-COMPLETE:90
+CLASS:CONFIDENTIAL
+COMMENT:User commentary text
+SEQUENCE:2
+DTSTART;TZID=America/New_York:20131213T131313
+CREATED:20170221T130512Z
+LAST-MODIFIED:20170221T130610Z
+END:VTODO
diff --git a/tests/libedata-cal/components/task-7.ics b/tests/libedata-cal/components/task-7.ics
new file mode 100644
index 0000000..bd01312
--- /dev/null
+++ b/tests/libedata-cal/components/task-7.ics
@@ -0,0 +1,17 @@
+BEGIN:VTODO
+UID:task-7
+DTSTAMP:20170221T130109Z
+SUMMARY:55% complete (Private)
+STATUS:IN-PROCESS
+PERCENT-COMPLETE:55
+CLASS:PRIVATE
+SEQUENCE:3
+PRIORITY:2
+CREATED:20170221T130447Z
+LAST-MODIFIED:20170221T130618Z
+BEGIN:VALARM
+TRIGGER:-PT30M
+ACTION:DISPLAY
+DESCRIPTION:Reminder
+END:VALARM
+END:VTODO
diff --git a/tests/libedata-cal/components/task-8.ics b/tests/libedata-cal/components/task-8.ics
new file mode 100644
index 0000000..f3ca458
--- /dev/null
+++ b/tests/libedata-cal/components/task-8.ics
@@ -0,0 +1,11 @@
+BEGIN:VTODO
+UID:task-8
+DTSTAMP:20170221T130109Z
+SUMMARY:Status - Cancelled
+STATUS:CANCELLED
+PERCENT-COMPLETE:33
+CLASS:PUBLIC
+SEQUENCE:1
+CREATED:20170221T130727Z
+LAST-MODIFIED:20170221T130727Z
+END:VTODO
diff --git a/tests/libedata-cal/components/task-9.ics b/tests/libedata-cal/components/task-9.ics
new file mode 100644
index 0000000..af66b26
--- /dev/null
+++ b/tests/libedata-cal/components/task-9.ics
@@ -0,0 +1,11 @@
+BEGIN:VTODO
+UID:task-9
+DTSTAMP:20170221T130109Z
+SUMMARY:With start date
+DTSTART;TZID=America/New_York:20170213T000000
+PERCENT-COMPLETE:0
+CLASS:PUBLIC
+SEQUENCE:1
+CREATED:20170221T132838Z
+LAST-MODIFIED:20170221T132838Z
+END:VTODO
diff --git a/tests/libedata-cal/test-cal-cache-intervals.c b/tests/libedata-cal/test-cal-cache-intervals.c
index 151e328..7d32622 100644
--- a/tests/libedata-cal/test-cal-cache-intervals.c
+++ b/tests/libedata-cal/test-cal-cache-intervals.c
@@ -66,20 +66,38 @@ compare_intervals (time_t x_start,
}
static GHashTable *
-search_in_intervals (GSList *intervals,
+search_in_intervals (ETimezoneCache *zone_cache,
+ GSList *intervals,
time_t start,
time_t end)
{
+ ECalBackendSExp *sexp;
+ struct icaltimetype itt_start, itt_end;
+ gchar *expr;
GSList *link;
GHashTable *res;
+ itt_start = icaltime_from_timet_with_zone (start, FALSE, NULL);
+ itt_end = icaltime_from_timet_with_zone (end, FALSE, NULL);
+
+ expr = g_strdup_printf ("(occur-in-time-range? (make-time \"%04d%02d%02dT%02d%02d%02dZ\") (make-time
\"%04d%02d%02dT%02d%02d%02dZ\"))",
+ itt_start.year, itt_start.month, itt_start.day, itt_start.hour, itt_start.minute,
itt_start.second,
+ itt_end.year, itt_end.month, itt_end.day, itt_end.hour, itt_end.minute, itt_end.second);
+
+ sexp = e_cal_backend_sexp_new (expr);
+
+ g_free (expr);
+
+ g_assert_nonnull (sexp);
+
res = g_hash_table_new_full ((GHashFunc) e_cal_component_id_hash, (GEqualFunc)
e_cal_component_id_equal,
(GDestroyNotify) e_cal_component_free_id, g_object_unref);
for (link = intervals; link; link = g_slist_next (link)) {
IntervalData *data = link->data;
- if (compare_intervals (start, end, data->start, data->end) == 0) {
+ if (compare_intervals (start, end, data->start, data->end) == 0 &&
+ e_cal_backend_sexp_match_comp (sexp, data->comp, zone_cache)) {
ECalComponentId *id = NULL;
id = e_cal_component_get_id (data->comp);
@@ -89,6 +107,8 @@ search_in_intervals (GSList *intervals,
}
}
+ g_object_unref (sexp);
+
return res;
}
@@ -164,6 +184,7 @@ test_intervals (TCUFixture *fixture,
GRand *myrand;
IntervalData *interval;
ECalComponent *comp;
+ ETimezoneCache *zone_cache;
GSList *l1, *intervals = NULL;
GHashTable *from_intervals;
gint num_deleted = 0;
@@ -171,6 +192,8 @@ test_intervals (TCUFixture *fixture,
gboolean success;
GError *error = NULL;
+ zone_cache = E_TIMEZONE_CACHE (fixture->cal_cache);
+
myrand = g_rand_new ();
for (ii = 0; ii < NUM_INTERVALS_CLOSED; ii++) {
@@ -221,7 +244,7 @@ test_intervals (TCUFixture *fixture,
g_assert_no_error (error);
g_assert (success);
- from_intervals = search_in_intervals (intervals, start, end);
+ from_intervals = search_in_intervals (zone_cache, intervals, start, end);
check_search_results (l1, from_intervals);
@@ -240,7 +263,7 @@ test_intervals (TCUFixture *fixture,
g_assert_no_error (error);
g_assert (success);
- from_intervals = search_in_intervals (intervals, start, end);
+ from_intervals = search_in_intervals (zone_cache, intervals, start, end);
check_search_results (l1, from_intervals);
@@ -281,7 +304,7 @@ test_intervals (TCUFixture *fixture,
for (ii = 0; ii < NUM_SEARCHES; ii++) {
start = g_rand_int_range (myrand, 0, 1000);
- end = g_rand_int_range (myrand, start, 2000);
+ end = g_rand_int_range (myrand, start + 1, 2000);
l1 = NULL;
@@ -289,7 +312,7 @@ test_intervals (TCUFixture *fixture,
g_assert_no_error (error);
g_assert (success);
- from_intervals = search_in_intervals (intervals, start, end);
+ from_intervals = search_in_intervals (zone_cache, intervals, start, end);
check_search_results (l1, from_intervals);
diff --git a/tests/libedata-cal/test-cal-cache-offline.c b/tests/libedata-cal/test-cal-cache-offline.c
index 1d0d183..a831157 100644
--- a/tests/libedata-cal/test-cal-cache-offline.c
+++ b/tests/libedata-cal/test-cal-cache-offline.c
@@ -1003,7 +1003,7 @@ gint
main (gint argc,
gchar **argv)
{
- TCUClosure closure = { 0 };
+ TCUClosure closure = { TCU_LOAD_COMPONENT_SET_NONE };
#if !GLIB_CHECK_VERSION (2, 35, 1)
g_type_init ();
diff --git a/tests/libedata-cal/test-cal-cache-search.c b/tests/libedata-cal/test-cal-cache-search.c
new file mode 100644
index 0000000..2253c29
--- /dev/null
+++ b/tests/libedata-cal/test-cal-cache-search.c
@@ -0,0 +1,470 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libecal/libecal.h>
+
+#include "test-cal-cache-utils.h"
+
+#define dd(x)
+
+static GHashTable *
+test_search_manual (ECalCache *cal_cache,
+ const gchar *expr)
+{
+ GSList *components = NULL, *link;
+ GHashTable *res;
+ ECalBackendSExp *sexp;
+ ETimezoneCache *zone_cache;
+ gboolean success;
+ GError *error = NULL;
+
+ res = g_hash_table_new_full ((GHashFunc) e_cal_component_id_hash, (GEqualFunc)
e_cal_component_id_equal,
+ (GDestroyNotify) e_cal_component_free_id, g_object_unref);
+
+ zone_cache = E_TIMEZONE_CACHE (cal_cache);
+
+ /* Get all the components stored in the summary. */
+ success = e_cal_cache_search_components (cal_cache, NULL, &components, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+ g_assert_nonnull (components);
+
+ sexp = e_cal_backend_sexp_new (expr);
+ g_assert (sexp != NULL);
+
+ for (link = components; link; link = g_slist_next (link)) {
+ ECalComponent *comp = link->data;
+
+ if (e_cal_backend_sexp_match_comp (sexp, comp, zone_cache)) {
+ ECalComponentId *id = NULL;
+
+ id = e_cal_component_get_id (comp);
+ g_assert_nonnull (id);
+
+ g_hash_table_insert (res, id, g_object_ref (comp));
+ }
+ }
+
+ g_slist_free_full (components, g_object_unref);
+ g_object_unref (sexp);
+
+ return res;
+}
+
+#if dd(1)+0
+static void
+test_search_dump_results (GSList *search_data,
+ GHashTable *should_be)
+{
+ GSList *link;
+ GHashTableIter iter;
+ gpointer key;
+ gint ii;
+
+ printf (" Found %d in ECalCache:\n", g_slist_length (search_data));
+ for (ii = 0, link = search_data; link; link = g_slist_next (link), ii++) {
+ ECalCacheSearchData *sd = link->data;
+
+ printf (" [%d]: %s%s%s\n", ii, sd->uid, sd->rid ? ", " : "", sd->rid ? sd->rid : "");
+ }
+
+ printf ("\n");
+ printf (" Found %d in traverse:\n", g_hash_table_size (should_be));
+
+ ii = 0;
+ g_hash_table_iter_init (&iter, should_be);
+ while (g_hash_table_iter_next (&iter, &key, NULL)) {
+ ECalComponentId *id = key;
+
+ printf (" [%d]: %s%s%s\n", ii, id->uid, id->rid ? ", " : "", id->rid ? id->rid : "");
+ ii++;
+ }
+
+ printf ("\n");
+}
+#endif
+
+static void
+test_search_result_equal (GSList *items,
+ GHashTable *should_be,
+ gboolean (* check_cb) (GHashTable *should_be, gpointer item_data))
+{
+ GSList *link;
+
+ g_assert_cmpint (g_slist_length (items), ==, g_hash_table_size (should_be));
+
+ for (link = items; link; link = g_slist_next (link)) {
+ g_assert (check_cb (should_be, link->data));
+ }
+}
+
+static gboolean
+search_data_check_cb (GHashTable *should_be,
+ gpointer item_data)
+{
+ ECalCacheSearchData *sd = item_data;
+ ECalComponentId id;
+
+ g_assert (sd != NULL);
+ g_assert (sd->uid != NULL);
+
+ id.uid = sd->uid;
+ id.rid = sd->rid;
+
+ return g_hash_table_contains (should_be, &id);
+}
+
+static gboolean
+component_check_cb (GHashTable *should_be,
+ gpointer item_data)
+{
+ ECalComponent *comp = item_data;
+ ECalComponentId *id;
+ gboolean contains;
+
+ g_assert (comp != NULL);
+
+ id = e_cal_component_get_id (comp);
+
+ g_assert (id != NULL);
+ g_assert (id->uid != NULL);
+
+ contains = g_hash_table_contains (should_be, id);
+
+ e_cal_component_free_id (id);
+
+ return contains;
+}
+
+static gboolean
+id_check_cb (GHashTable *should_be,
+ gpointer item_data)
+{
+ ECalComponentId *id = item_data;
+
+ g_assert (id != NULL);
+ g_assert (id->uid != NULL);
+
+ return g_hash_table_contains (should_be, id);
+}
+
+static void
+test_search_expr (TCUFixture *fixture,
+ const gchar *expr,
+ const gchar *expects)
+{
+ GSList *items = NULL;
+ GHashTable *should_be;
+ gboolean success;
+ GError *error = NULL;
+
+ should_be = test_search_manual (fixture->cal_cache, expr);
+ g_assert_nonnull (should_be);
+
+ success = e_cal_cache_search (fixture->cal_cache, expr, &items, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ dd (test_search_dump_results (items, should_be));
+
+ test_search_result_equal (items, should_be, search_data_check_cb);
+
+ g_slist_free_full (items, e_cal_cache_search_data_free);
+ items = NULL;
+
+ success = e_cal_cache_search_components (fixture->cal_cache, expr, &items, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ test_search_result_equal (items, should_be, component_check_cb);
+
+ g_slist_free_full (items, g_object_unref);
+ items = NULL;
+
+ success = e_cal_cache_search_ids (fixture->cal_cache, expr, &items, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ if (expects) {
+ GSList *link;
+ gboolean negate = *expects == '!';
+
+ if (negate)
+ expects++;
+
+ for (link = items; link; link = g_slist_next (link)) {
+ ECalComponentId *id = link->data;
+
+ if (g_strcmp0 (id->uid, expects) == 0)
+ break;
+ }
+
+ if (link && negate)
+ g_error ("Found '%s' in result of '%s', though it should not be there", expects,
expr);
+ else if (!link && !negate)
+ g_error ("Not found '%s' in result of '%s', though it should be there", expects,
expr);
+ }
+
+ test_search_result_equal (items, should_be, id_check_cb);
+
+ g_slist_free_full (items, (GDestroyNotify) e_cal_component_free_id);
+
+ g_hash_table_destroy (should_be);
+}
+
+static void
+test_search (TCUFixture *fixture,
+ const gchar *expr,
+ const gchar *expects)
+{
+ gchar *not_expr;
+
+ test_search_expr (fixture, expr, expects);
+
+ not_expr = g_strdup_printf ("(not (%s))", expr);
+ test_search_expr (fixture, not_expr, NULL);
+ g_free (not_expr);
+}
+
+static void
+test_search_uid (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(uid? \"event-3\")", "event-3");
+ test_search (fixture, "(uid? \"event-6\")", "event-6");
+ test_search (fixture, "(or (uid? \"event-3\") (uid? \"event-6\"))", "event-3");
+ test_search (fixture, "(and (uid? \"event-3\") (uid? \"event-6\"))", "!event-3");
+}
+
+static void
+test_search_occur_in_time_range (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(occur-in-time-range? (make-time \"20010101T000000Z\") (make-time
\"20010101T010000Z\"))", "!event-1");
+ test_search (fixture, "(occur-in-time-range? (make-time \"20170209T000000Z\") (make-time
\"20170210T000000Z\"))", "event-1");
+ test_search (fixture, "(occur-in-time-range? (make-time \"20170209T020000Z\") (make-time
\"20170209T023000Z\"))", "event-1");
+ test_search (fixture, "(occur-in-time-range? (make-time \"20111231T000000Z\") (make-time
\"20111231T595959Z\"))", "event-5");
+
+ /* the second instance of event-6 */
+ test_search (fixture, "(occur-in-time-range? (make-time \"20170221T130000Z\") (make-time
\"20170221T140000Z\"))", "event-6");
+ test_search (fixture, "(occur-in-time-range? (make-time \"20170221T130000Z\") (make-time
\"20170221T140000Z\") \"America/New_York\")", "event-6");
+ test_search (fixture, "(occur-in-time-range? (make-time \"20170221T190000Z\") (make-time
\"20170221T200000Z\") \"Europe/Berlin\")", "!event-6");
+ test_search (fixture, "(occur-in-time-range? (make-time \"20170221T130000Z\") (make-time
\"20170221T140000Z\") \"Europe/Berlin\")", "event-6");
+}
+
+static void
+test_search_due_in_time_range (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(due-in-time-range? (make-time \"20170101T000000Z\") (make-time
\"20170101T010000Z\"))", "!task-4");
+ test_search (fixture, "(due-in-time-range? (make-time \"20170228T000000Z\") (make-time
\"20170302T000000Z\"))", "task-4");
+}
+
+static void
+test_search_contains (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ const TCUClosure *closure = user_data;
+ gboolean searches_events = closure && closure->load_set == TCU_LOAD_COMPONENT_SET_EVENTS;
+
+ test_search (fixture, "(contains? \"any\" \"party\")", searches_events ? "event-5" : NULL);
+ test_search (fixture, "(contains? \"comment\" \"mentar\")", searches_events ? "event-8" : "task-6");
+ test_search (fixture, "(contains? \"description\" \"with\")", searches_events ? "event-1" : "task-3");
+ test_search (fixture, "(contains? \"summary\" \"meet\")", searches_events ? "event-8" : NULL);
+ test_search (fixture, "(contains? \"location\" \"kitchen\")", searches_events ? "event-3" : "task-5");
+ test_search (fixture, "(contains? \"attendee\" \"CharLie\")", searches_events ? "event-9" : NULL);
+ test_search (fixture, "(contains? \"organizer\" \"bOb\")", searches_events ? "event-8" : NULL);
+ test_search (fixture, "(contains? \"classification\" \"Public\")", searches_events ? "event-4" :
"task-4");
+ test_search (fixture, "(contains? \"classification\" \"Private\")", searches_events ? "event-3" :
"task-7");
+ test_search (fixture, "(contains? \"classification\" \"Confidential\")", searches_events ? "event-2"
: "task-6");
+ test_search (fixture, "(contains? \"status\" \"NOT STARTED\")", searches_events ? NULL : "task-1");
+ test_search (fixture, "(contains? \"status\" \"COMPLETED\")", searches_events ? NULL : "task-4");
+ test_search (fixture, "(contains? \"status\" \"CANCELLED\")", searches_events ? NULL : "task-8");
+ test_search (fixture, "(contains? \"status\" \"IN PROGRESS\")", searches_events ? NULL : "task-7");
+ test_search (fixture, "(contains? \"priority\" \"HIGH\")", searches_events ? NULL : "task-7");
+ test_search (fixture, "(contains? \"priority\" \"NORMAL\")", searches_events ? NULL : "task-6");
+ test_search (fixture, "(contains? \"priority\" \"LOW\")", searches_events ? NULL : "task-5");
+ test_search (fixture, "(contains? \"priority\" \"UNDEFINED\")", searches_events ? NULL : "task-1");
+}
+
+static void
+test_search_has_start (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ const TCUClosure *closure = user_data;
+ gboolean searches_events = closure && closure->load_set == TCU_LOAD_COMPONENT_SET_EVENTS;
+
+ test_search (fixture, "(has-start?)", searches_events ? "event-1" : "task-9");
+ test_search (fixture, "(has-start?)", searches_events ? "event-1" : "!task-8");
+ test_search (fixture, "(not (has-start?))", searches_events ? "!event-1" : "!task-9");
+ test_search (fixture, "(not (has-start?))", searches_events ? "!event-1" : "task-8");
+}
+
+static void
+test_search_has_alarms (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ const TCUClosure *closure = user_data;
+ gboolean searches_events = closure && closure->load_set == TCU_LOAD_COMPONENT_SET_EVENTS;
+
+ test_search (fixture, "(has-alarms?)", searches_events ? "event-1" : "task-7");
+ test_search (fixture, "(has-alarms?)", searches_events ? "event-1" : "!task-6");
+ test_search (fixture, "(not (has-alarms?))", searches_events ? "!event-1" : "!task-7");
+ test_search (fixture, "(not (has-alarms?))", searches_events ? "!event-1" : "task-6");
+}
+
+static void
+test_search_has_alarms_in_range (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ const TCUClosure *closure = user_data;
+ gboolean searches_events = closure && closure->load_set == TCU_LOAD_COMPONENT_SET_EVENTS;
+
+ test_search (fixture, "(has-alarms-in-range? (make-time \"20091229T230000Z\") (make-time
\"20091231T010000Z\"))",
+ searches_events ? "event-5" : "!task-7");
+}
+
+static void
+test_search_has_recurrences (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(has-recurrences?)", "event-6");
+ test_search (fixture, "(not (has-recurrences?))", "!event-6");
+}
+
+static void
+test_search_has_categories (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(has-categories? #f)", "!event-2");
+ test_search (fixture, "(has-categories? \"Holiday\")", "event-4");
+ test_search (fixture, "(has-categories? \"Hard\" \"Work\")", "event-2");
+ test_search (fixture, "(has-categories? \"Hard\" \"Work\")", "!event-4");
+}
+
+static void
+test_search_is_completed (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(is-completed?)", "task-4");
+ test_search (fixture, "(is-completed?)", "!task-5");
+ test_search (fixture, "(not (is-completed?))", "!task-4");
+}
+
+static void
+test_search_completed_before (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(completed-before? (make-time \"20170221T000000Z\"))", "!task-4");
+ test_search (fixture, "(completed-before? (make-time \"20170222T000000Z\"))", "task-4");
+}
+
+static void
+test_search_has_attachments (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(has-attachments?)", "event-7");
+ test_search (fixture, "(not (has-attachments?))", "!event-7");
+}
+
+static void
+test_search_percent_complete (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(< (percent-complete?) 30)", "task-5");
+ test_search (fixture, "(< (percent-complete?) 30)", "!task-7");
+}
+
+static void
+test_search_occurrences_count (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture, "(and (= (occurrences-count?) 1) (occur-in-time-range? (make-time
\"20170209T000000Z\") (make-time \"20170210T000000Z\")))", "event-1");
+ test_search (fixture, "(= (occurrences-count? (make-time \"20170209T000000Z\") (make-time
\"20170210T000000Z\")) 1)", "event-1");
+}
+
+static void
+test_search_complex (TCUFixture *fixture,
+ gconstpointer user_data)
+{
+ test_search (fixture,
+ "(or "
+ "(and (not (is-completed?)) (has-start?) (not (has-alarms?)))"
+ "(contains? \"summary\" \"-on-\")"
+ "(has-attachments?)"
+ ")", "event-3");
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ TCUClosure closure_events = { TCU_LOAD_COMPONENT_SET_EVENTS };
+ TCUClosure closure_tasks = { TCU_LOAD_COMPONENT_SET_TASKS };
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ /* Ensure that the client and server get the same locale */
+ g_assert (g_setenv ("LC_ALL", "en_US.UTF-8", TRUE));
+ setlocale (LC_ALL, "");
+
+ g_test_add ("/ECalCache/Search/Uid", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_uid, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/OccurInTimeRange", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_occur_in_time_range, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/DueInTimeRange", TCUFixture, &closure_tasks,
+ tcu_fixture_setup, test_search_due_in_time_range, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/Contains/Events", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_contains, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/Contains/Tasks", TCUFixture, &closure_tasks,
+ tcu_fixture_setup, test_search_contains, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasStart/Events", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_has_start, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasStart/Tasks", TCUFixture, &closure_tasks,
+ tcu_fixture_setup, test_search_has_start, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasAlarms/Events", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_has_alarms, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasAlarms/Tasks", TCUFixture, &closure_tasks,
+ tcu_fixture_setup, test_search_has_alarms, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasAlarmsInRange/Events", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_has_alarms_in_range, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasAlarmsInRange/Tasks", TCUFixture, &closure_tasks,
+ tcu_fixture_setup, test_search_has_alarms_in_range, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasRecurrences", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_has_recurrences, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasCategories", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_has_categories, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/IsCompleted", TCUFixture, &closure_tasks,
+ tcu_fixture_setup, test_search_is_completed, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/CompletedBefore", TCUFixture, &closure_tasks,
+ tcu_fixture_setup, test_search_completed_before, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/HasAttachments", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_has_attachments, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/PercentComplete", TCUFixture, &closure_tasks,
+ tcu_fixture_setup, test_search_percent_complete, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/OccurrencesCount", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_occurrences_count, tcu_fixture_teardown);
+ g_test_add ("/ECalCache/Search/Complex", TCUFixture, &closure_events,
+ tcu_fixture_setup, test_search_complex, tcu_fixture_teardown);
+
+ return g_test_run ();
+}
diff --git a/tests/libedata-cal/test-cal-cache-utils.c b/tests/libedata-cal/test-cal-cache-utils.c
index b14e3a4..c109466 100644
--- a/tests/libedata-cal/test-cal-cache-utils.c
+++ b/tests/libedata-cal/test-cal-cache-utils.c
@@ -54,7 +54,7 @@ void
tcu_fixture_setup (TCUFixture *fixture,
gconstpointer user_data)
{
- /* TCUClosure *closure = (TCUClosure *) user_data; */
+ const TCUClosure *closure = user_data;
gchar *filename, *directory;
GError *error = NULL;
@@ -75,6 +75,31 @@ tcu_fixture_setup (TCUFixture *fixture,
g_error ("Failed to create the ECalCache: %s", error->message);
g_free (filename);
+
+ if (closure) {
+ if (closure->load_set == TCU_LOAD_COMPONENT_SET_EVENTS) {
+ tcu_add_component_from_test_case (fixture, "event-1", NULL);
+ tcu_add_component_from_test_case (fixture, "event-2", NULL);
+ tcu_add_component_from_test_case (fixture, "event-3", NULL);
+ tcu_add_component_from_test_case (fixture, "event-4", NULL);
+ tcu_add_component_from_test_case (fixture, "event-5", NULL);
+ tcu_add_component_from_test_case (fixture, "event-6", NULL);
+ tcu_add_component_from_test_case (fixture, "event-6-a", NULL);
+ tcu_add_component_from_test_case (fixture, "event-7", NULL);
+ tcu_add_component_from_test_case (fixture, "event-8", NULL);
+ tcu_add_component_from_test_case (fixture, "event-9", NULL);
+ } else if (closure->load_set == TCU_LOAD_COMPONENT_SET_TASKS) {
+ tcu_add_component_from_test_case (fixture, "task-1", NULL);
+ tcu_add_component_from_test_case (fixture, "task-2", NULL);
+ tcu_add_component_from_test_case (fixture, "task-3", NULL);
+ tcu_add_component_from_test_case (fixture, "task-4", NULL);
+ tcu_add_component_from_test_case (fixture, "task-5", NULL);
+ tcu_add_component_from_test_case (fixture, "task-6", NULL);
+ tcu_add_component_from_test_case (fixture, "task-7", NULL);
+ tcu_add_component_from_test_case (fixture, "task-8", NULL);
+ tcu_add_component_from_test_case (fixture, "task-9", NULL);
+ }
+ }
}
void
diff --git a/tests/libedata-cal/test-cal-cache-utils.h b/tests/libedata-cal/test-cal-cache-utils.h
index 373f93e..d3616fc 100644
--- a/tests/libedata-cal/test-cal-cache-utils.h
+++ b/tests/libedata-cal/test-cal-cache-utils.h
@@ -22,12 +22,18 @@
G_BEGIN_DECLS
+typedef enum {
+ TCU_LOAD_COMPONENT_SET_NONE,
+ TCU_LOAD_COMPONENT_SET_EVENTS,
+ TCU_LOAD_COMPONENT_SET_TASKS
+} TCULoadComponentSet;
+
typedef struct {
ECalCache *cal_cache;
} TCUFixture;
typedef struct {
- gint dummy;
+ TCULoadComponentSet load_set;
} TCUClosure;
void tcu_fixture_setup (TCUFixture *fixture,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]