e94e33b4d44c7eb7831d7a227f2f2c3e09aac634
[platform/upstream/evolution-data-server.git] / tests / libedataserverui / test-client-examine-auth.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 #include <libedataserver/e-source-group.h>
4 #include <libedataserverui/e-client-utils.h>
5 #include <libedataserverui/e-passwords.h>
6
7 static void stop_main_loop (gint stop_result);
8 static void report_error (const gchar *operation, GError **error);
9 static gpointer foreach_configured_source_async_start (ESource **source);
10 static gboolean foreach_configured_source_async_next (gpointer *foreach_async_data, ESource **source);
11 static gboolean foreach_async (void);
12
13 static gint running_async = 0;
14 static EClientSourceType source_type = E_CLIENT_SOURCE_TYPE_CONTACTS;
15
16 static GSList *
17 get_known_prop_names (void)
18 {
19         GSList *prop_names = NULL;
20
21         prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
22         prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
23         prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENED);
24         prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENING);
25         prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CACHE_DIR);
26         prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CAPABILITIES);
27
28         return prop_names;
29 }
30
31 typedef struct _ExtraValues {
32         gpointer async_data;
33
34         GSList *todo_prop_names;
35         GHashTable *retrieved_props;
36 } ExtraValues;
37
38 static void
39 extra_values_free (ExtraValues *evals)
40 {
41         if (!evals)
42                 return;
43
44         g_slist_free (evals->todo_prop_names);
45         g_hash_table_destroy (evals->retrieved_props);
46         g_free (evals);
47 }
48
49 static void
50 print_each_property (gpointer prop_name,
51                      gpointer prop_value,
52                      gpointer user_data)
53 {
54         g_return_if_fail (prop_name != NULL);
55
56         if (prop_value == NULL) {
57                 g_print ("\t   %s: NULL\n", (const gchar *) prop_name);
58                 return;
59         }
60
61         g_print ("\t   %s: ", (const gchar *) prop_name);
62
63         if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
64                 GSList *values = e_client_util_parse_comma_strings (prop_value), *v;
65
66                 for (v = values; v; v = v->next) {
67                         if (v != values)
68                                 g_print (", ");
69
70                         g_print ("'%s'", (const gchar *) v->data);
71                 }
72
73                 e_client_util_free_string_slist (values);
74         } else {
75                 g_print ("'%s'", (const gchar *) prop_value);
76         }
77
78         g_print ("\n");
79 }
80
81 static void
82 print_values (const ExtraValues *evals,
83               EClient *client)
84 {
85         const GSList *values;
86
87         g_return_if_fail (evals != NULL);
88
89         g_print ("\treadonly:%s\n", e_client_is_readonly (client) ? "yes" : "no");
90         g_print ("\tonline:%s\n", e_client_is_online (client) ? "yes" : "no");
91         g_print ("\topened:%s\n", e_client_is_opened (client) ? "yes" : "no");
92         g_print ("\tcapabilities: ");
93         values = e_client_get_capabilities (client);
94         if (!values) {
95                 g_print ("NULL");
96         } else {
97                 while (values) {
98                         const gchar *cap = values->data;
99
100                         g_print ("'%s'", cap);
101                         if (!e_client_check_capability (client, cap))
102                                 g_print (" (not found in EClient)");
103
104                         values = values->next;
105
106                         if (values)
107                                 g_print (", ");
108                 }
109         }
110         g_print ("\n");
111
112         g_print ("\tbackend properties:\n");
113         g_hash_table_foreach (evals->retrieved_props, print_each_property, NULL);
114 }
115
116 static void
117 identify_source (ESource *source)
118 {
119         const gchar *name, *uri;
120         gchar *abs_uri = NULL;
121
122         g_return_if_fail (source != NULL);
123
124         name = e_source_peek_name (source);
125         if (!name)
126                 name = "Unknown name";
127
128         uri = e_source_peek_absolute_uri (source);
129         if (!uri) {
130                 abs_uri = e_source_build_absolute_uri (source);
131                 uri = abs_uri;
132         }
133         if (!uri)
134                 uri = e_source_peek_relative_uri (source);
135         if (!uri)
136                 uri = "Unknown uri";
137
138         g_print ("\n   Checking source '%s' (%s)\n", name, uri);
139
140         g_free (abs_uri);
141 }
142
143 static void client_opened_async (GObject *source_object, GAsyncResult *result, gpointer async_data);
144
145 static void
146 continue_next_source (gpointer async_data)
147 {
148         ESource *source = NULL;
149
150         g_return_if_fail (async_data != NULL);
151
152         while (async_data && foreach_configured_source_async_next (&async_data, &source)) {
153                 identify_source (source);
154                 e_client_utils_open_new (source, source_type, TRUE, NULL,
155                         e_client_utils_authenticate_handler, NULL,
156                         client_opened_async, async_data);
157                 break;
158         }
159
160         if (!async_data) {
161                 running_async--;
162                 if (!running_async) {
163                         while (source_type++, source_type < E_CLIENT_SOURCE_TYPE_LAST) {
164                                 if (foreach_async ())
165                                         return;
166                         }
167
168                         stop_main_loop (0);
169                 }
170         }
171 }
172
173 static void
174 client_got_backend_property_async (GObject *source_object,
175                                    GAsyncResult *result,
176                                    gpointer user_data)
177 {
178         ExtraValues *evals = user_data;
179         gchar *prop_value = NULL;
180         GError *error = NULL;
181         EClient *client;
182
183         g_return_if_fail (source_object != NULL);
184         g_return_if_fail (E_IS_CLIENT (source_object));
185         g_return_if_fail (evals != NULL);
186
187         client = E_CLIENT (source_object);
188
189         if (!e_client_get_backend_property_finish (client, result, &prop_value, &error)) {
190                 report_error ("get backend property finish", &error);
191         }
192
193         g_hash_table_insert (evals->retrieved_props, evals->todo_prop_names->data, prop_value);
194         evals->todo_prop_names = g_slist_remove (evals->todo_prop_names, evals->todo_prop_names->data);
195
196         if (!evals->todo_prop_names) {
197                 /* to cache them, as it can be fetched with idle as well */
198                 e_client_get_capabilities (client);
199
200                 print_values (evals, client);
201
202                 g_object_unref (source_object);
203
204                 continue_next_source (evals->async_data);
205                 extra_values_free (evals);
206         } else {
207                 e_client_get_backend_property (client, evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
208         }
209 }
210
211 static void
212 client_set_backend_property_async (GObject *source_object,
213                                    GAsyncResult *result,
214                                    gpointer user_data)
215 {
216         ExtraValues *evals = user_data;
217         GError *error = NULL;
218         EClient *client;
219
220         g_return_if_fail (source_object != NULL);
221         g_return_if_fail (E_IS_CLIENT (source_object));
222         g_return_if_fail (evals != NULL);
223
224         client = E_CLIENT (source_object);
225
226         if (!e_client_set_backend_property_finish (client, result, &error)) {
227                 /* it may fail on the set_backend_property */
228                 g_clear_error (&error);
229         } else {
230                 g_printerr ("   Might fail on set_backend_property, but reported success\n");
231         }
232
233         e_client_get_backend_property (client, evals->todo_prop_names->data, NULL, client_got_backend_property_async, evals);
234 }
235
236 static void
237 client_opened_async (GObject *source_object,
238                      GAsyncResult *result,
239                      gpointer async_data)
240 {
241         ExtraValues *evals;
242         GError *error = NULL;
243         EClient *client = NULL;
244
245         g_return_if_fail (source_object != NULL);
246         g_return_if_fail (E_IS_SOURCE (source_object));
247         g_return_if_fail (async_data != NULL);
248
249         if (!e_client_utils_open_new_finish (E_SOURCE (source_object), result, &client, &error)) {
250                 report_error ("client utils open new finish", &error);
251                 continue_next_source (async_data);
252                 return;
253         }
254
255         evals = g_new0 (ExtraValues, 1);
256         evals->async_data = async_data;
257         evals->todo_prop_names = get_known_prop_names ();
258         evals->retrieved_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
259
260         e_client_set_backend_property (client, "*unknown*property*", "*value*", NULL, client_set_backend_property_async, evals);
261 }
262
263 static gboolean
264 foreach_async (void)
265 {
266         gpointer async_data;
267         ESource *source = NULL;
268
269         async_data = foreach_configured_source_async_start (&source);
270         if (!async_data) {
271                 stop_main_loop (1);
272                 return FALSE;
273         }
274
275         running_async++;
276
277         identify_source (source);
278         e_client_utils_open_new (source, source_type, TRUE, NULL,
279                 e_client_utils_authenticate_handler, NULL,
280                 client_opened_async, async_data);
281
282         return TRUE;
283 }
284
285 static gboolean
286 in_main_thread_idle_cb (gpointer unused)
287 {
288         if (!foreach_async ())
289                 return FALSE;
290
291         return FALSE;
292 }
293
294 static GMainLoop *loop = NULL;
295 static gint main_stop_result = 0;
296
297 static void
298 stop_main_loop (gint stop_result)
299 {
300         g_return_if_fail (loop != NULL);
301
302         main_stop_result = stop_result;
303         g_main_loop_quit (loop);
304 }
305
306 static gint
307 get_main_loop_stop_result (void)
308 {
309         return main_stop_result;
310 }
311
312 struct ForeachConfiguredData
313 {
314         ESourceList *source_list;
315         GSList *current_group;
316         GSList *current_source;
317 };
318
319 static gpointer
320 foreach_configured_source_async_start (ESource **source)
321 {
322         struct ForeachConfiguredData *async_data;
323         ESourceList *source_list = NULL;
324         GError *error = NULL;
325
326         g_return_val_if_fail (source != NULL, NULL);
327
328         if (!e_client_utils_get_sources (&source_list, source_type, &error)) {
329                 report_error ("get sources", &error);
330                 return NULL;
331         }
332
333         g_return_val_if_fail (source_list != NULL, NULL);
334
335         async_data = g_new0 (struct ForeachConfiguredData, 1);
336         async_data->source_list = source_list;
337         async_data->current_group = e_source_list_peek_groups (source_list);
338         if (!async_data->current_group) {
339                 gpointer ad = async_data;
340
341                 foreach_configured_source_async_next (&ad, source);
342                 return ad;
343         }
344
345         async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
346         if (!async_data->current_source) {
347                 gpointer ad = async_data;
348
349                 if (foreach_configured_source_async_next (&ad, source))
350                         return ad;
351
352                 return NULL;
353         }
354
355         *source = async_data->current_source->data;
356
357         return async_data;
358 }
359
360 static gboolean
361 foreach_configured_source_async_next (gpointer *foreach_async_data,
362                                       ESource **source)
363 {
364         struct ForeachConfiguredData *async_data;
365
366         g_return_val_if_fail (foreach_async_data != NULL, FALSE);
367         g_return_val_if_fail (source != NULL, FALSE);
368
369         async_data = *foreach_async_data;
370         g_return_val_if_fail (async_data != NULL, FALSE);
371         g_return_val_if_fail (async_data->source_list != NULL, FALSE);
372         g_return_val_if_fail (async_data->current_group != NULL, FALSE);
373
374         if (async_data->current_source)
375                 async_data->current_source = async_data->current_source->next;
376         if (async_data->current_source) {
377                 *source = async_data->current_source->data;
378                 return TRUE;
379         }
380
381         do {
382                 async_data->current_group = async_data->current_group->next;
383                 if (async_data->current_group)
384                         async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
385         } while (async_data->current_group && !async_data->current_source);
386
387         if (async_data->current_source) {
388                 *source = async_data->current_source->data;
389                 return TRUE;
390         }
391
392         g_object_unref (async_data->source_list);
393         g_free (async_data);
394
395         *foreach_async_data = NULL;
396
397         return FALSE;
398 }
399
400 static void
401 report_error (const gchar *operation,
402               GError **error)
403 {
404         g_return_if_fail (operation != NULL);
405
406         g_printerr ("Failed to %s: %s\n", operation, (error && *error) ? (*error)->message : "Unknown error");
407
408         g_clear_error (error);
409 }
410
411 gint
412 main (gint argc,
413       gchar **argv)
414 {
415         g_type_init ();
416         #if !GLIB_CHECK_VERSION(2,31,0)
417         g_thread_init (NULL);
418         #endif
419         gtk_init (&argc, &argv);
420
421         e_passwords_init ();
422
423         g_idle_add (in_main_thread_idle_cb, NULL);
424
425         loop = g_main_loop_new (NULL, FALSE);
426         g_main_loop_run (loop);
427         g_main_loop_unref (loop);
428
429         return get_main_loop_stop_result ();
430 }