1 /*
2  * testing-extension.c
3  * This file is part of libpeas
4  *
5  * Copyright (C) 2011-2014 - Garrett Regier
6  *
7  * libpeas is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * libpeas is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 
30 #include <glib.h>
31 #include <libpeas/peas.h>
32 
33 #include "testing.h"
34 #include "testing-extension.h"
35 
36 #include "introspection-abstract.h"
37 #include "introspection-base.h"
38 #include "introspection-callable.h"
39 #include "introspection-has-prerequisite.h"
40 #include "introspection-unimplemented.h"
41 
42 typedef struct _TestFixture TestFixture;
43 
44 struct _TestFixture {
45   PeasEngine *engine;
46   PeasPluginInfo *info;
47 };
48 
49 static gchar *loader = NULL;
50 static gchar *extension_plugin = NULL;
51 
52 static void
test_setup(TestFixture * fixture,gconstpointer data)53 test_setup (TestFixture    *fixture,
54             gconstpointer  data)
55 {
56   fixture->engine = testing_engine_new ();
57   peas_engine_enable_loader (fixture->engine, loader);
58   fixture->info = peas_engine_get_plugin_info (fixture->engine,
59                                                extension_plugin);
60 }
61 
62 static void
test_teardown(TestFixture * fixture,gconstpointer data)63 test_teardown (TestFixture    *fixture,
64                gconstpointer  data)
65 {
66   testing_engine_free (fixture->engine);
67 }
68 
69 static void
test_runner(TestFixture * fixture,gconstpointer data)70 test_runner  (TestFixture   *fixture,
71               gconstpointer  data)
72 {
73   g_assert (fixture->info != NULL);
74   g_assert (peas_engine_load_plugin (fixture->engine, fixture->info));
75 
76   ((void (*) (PeasEngine *, PeasPluginInfo *)) data) (fixture->engine,
77                                                       fixture->info);
78 }
79 
80 static void
test_extension_garbage_collect(PeasEngine * engine,PeasPluginInfo * info)81 test_extension_garbage_collect (PeasEngine     *engine,
82                                 PeasPluginInfo *info)
83 {
84   gchar **loaded_plugins;
85 
86   peas_engine_garbage_collect (engine);
87 
88   /* Check that we can collect the garbage when no plugins are loaded */
89   g_assert (peas_engine_unload_plugin (engine, info));
90 
91   loaded_plugins = peas_engine_get_loaded_plugins (engine);
92   g_assert_cmpstr (loaded_plugins[0], ==, NULL);
93   g_strfreev (loaded_plugins);
94 
95   peas_engine_garbage_collect (engine);
96 }
97 
98 static void
test_extension_provides_valid(PeasEngine * engine,PeasPluginInfo * info)99 test_extension_provides_valid (PeasEngine     *engine,
100                                PeasPluginInfo *info)
101 {
102   g_assert (peas_engine_provides_extension (engine, info,
103                                             INTROSPECTION_TYPE_CALLABLE));
104 }
105 
106 static void
test_extension_provides_invalid(PeasEngine * engine,PeasPluginInfo * info)107 test_extension_provides_invalid (PeasEngine     *engine,
108                                  PeasPluginInfo *info)
109 {
110 
111   testing_util_push_log_hook ("*assertion*G_TYPE_IS_INTERFACE*failed");
112 
113   /* Invalid GType */
114   peas_engine_provides_extension (engine, info, G_TYPE_INVALID);
115 
116 
117   /* GObject but not a GInterface */
118   peas_engine_provides_extension (engine, info, PEAS_TYPE_ENGINE);
119 
120 
121   /* Does not implement this GType */
122   g_assert (!peas_engine_provides_extension (engine, info,
123                                              INTROSPECTION_TYPE_UNIMPLEMENTED));
124 
125   /* Not loaded */
126   g_assert (peas_engine_unload_plugin (engine, info));
127   g_assert (!peas_engine_provides_extension (engine, info,
128                                              INTROSPECTION_TYPE_CALLABLE));
129 }
130 
131 static void
test_extension_create_valid(PeasEngine * engine,PeasPluginInfo * info)132 test_extension_create_valid (PeasEngine     *engine,
133                              PeasPluginInfo *info)
134 {
135   PeasExtension *extension;
136 
137   extension = peas_engine_create_extension (engine, info,
138                                             INTROSPECTION_TYPE_CALLABLE,
139                                             NULL);
140 
141   g_assert (PEAS_IS_EXTENSION (extension));
142   g_assert (INTROSPECTION_IS_CALLABLE (extension));
143 
144   g_object_unref (extension);
145 }
146 
147 static void
test_extension_create_valid_without_properties(PeasEngine * engine,PeasPluginInfo * info)148 test_extension_create_valid_without_properties (PeasEngine     *engine,
149                                                 PeasPluginInfo *info)
150 {
151   PeasExtension *extension;
152 
153   extension =
154     peas_engine_create_extension_with_properties (engine, info,
155                                                   INTROSPECTION_TYPE_CALLABLE,
156                                                   0, NULL, NULL);
157 
158   g_assert (PEAS_IS_EXTENSION (extension));
159   g_assert (INTROSPECTION_IS_CALLABLE (extension));
160 
161   g_object_unref (extension);
162 }
163 
164 static void
test_extension_create_valid_with_properties(PeasEngine * engine,PeasPluginInfo * info)165 test_extension_create_valid_with_properties (PeasEngine     *engine,
166                                              PeasPluginInfo *info)
167 {
168   PeasExtension *extension;
169   IntrospectionAbstract *abstract;
170   GValue prop_values[1] = { G_VALUE_INIT };
171   const gchar *prop_names[1] = { "abstract-property" };
172 
173   g_assert (peas_engine_load_plugin (engine, info));
174 
175   g_value_init (&prop_values[0], G_TYPE_INT);
176   g_value_set_int (&prop_values[0], 47);
177   extension =
178       peas_engine_create_extension_with_properties (engine, info,
179                                                     INTROSPECTION_TYPE_ABSTRACT,
180                                                     G_N_ELEMENTS (prop_values),
181                                                     prop_names,
182                                                     prop_values);
183   abstract = INTROSPECTION_ABSTRACT (extension);
184   g_assert_cmpint (introspection_abstract_get_value (abstract), ==, 47);
185 
186   g_object_unref (extension);
187   g_value_unset (&prop_values[0]);
188 }
189 
190 static void
test_extension_create_invalid(PeasEngine * engine,PeasPluginInfo * info)191 test_extension_create_invalid (PeasEngine     *engine,
192                                PeasPluginInfo *info)
193 {
194   PeasExtension *extension;
195 
196   testing_util_push_log_hook ("*assertion*G_TYPE_IS_INTERFACE*failed");
197   testing_util_push_log_hook ("*does not provide a 'IntrospectionUnimplemented' extension");
198   testing_util_push_log_hook ("*type 'IntrospectionCallable' has no property named 'does-not-exist'");
199   testing_util_push_log_hook ("*assertion*peas_plugin_info_is_loaded*failed");
200 
201   /* Invalid GType */
202   extension = peas_engine_create_extension (engine, info, G_TYPE_INVALID, NULL);
203   g_assert (!PEAS_IS_EXTENSION (extension));
204 
205 
206   /* GObject but not a GInterface */
207   extension = peas_engine_create_extension (engine, info, PEAS_TYPE_ENGINE, NULL);
208   g_assert (!PEAS_IS_EXTENSION (extension));
209 
210 
211   /* Does not implement this GType */
212   extension = peas_engine_create_extension (engine, info,
213                                             INTROSPECTION_TYPE_UNIMPLEMENTED,
214                                             NULL);
215   g_assert (!PEAS_IS_EXTENSION (extension));
216 
217   /* Interface does not have a specified property */
218   extension = peas_engine_create_extension (engine, info,
219                                             INTROSPECTION_TYPE_CALLABLE,
220                                             "does-not-exist", "",
221                                             NULL);
222   g_assert (!PEAS_IS_EXTENSION (extension));
223 
224   /* Not loaded */
225   g_assert (peas_engine_unload_plugin (engine, info));
226   extension = peas_engine_create_extension (engine, info,
227                                             INTROSPECTION_TYPE_CALLABLE,
228                                             NULL);
229   g_assert (!PEAS_IS_EXTENSION (extension));
230 }
231 
232 static void
test_extension_create_invalid_with_properties(PeasEngine * engine,PeasPluginInfo * info)233 test_extension_create_invalid_with_properties (PeasEngine     *engine,
234                                                PeasPluginInfo *info)
235 {
236   PeasExtension *extension;
237   GValue prop_values[1] = { G_VALUE_INIT };
238   const gchar *prop_names[1] = { NULL };
239   GValue prop_values2[1] = { G_VALUE_INIT };
240   const gchar *prop_names2[1] = { "does-not-exist" };
241 
242   g_value_init (&prop_values[0], G_TYPE_STRING);
243   g_value_set_string (&prop_values[0], "foo");
244 
245   testing_util_push_log_hook ("*assertion*G_TYPE_IS_INTERFACE*failed");
246   testing_util_push_log_hook ("*does not provide a 'IntrospectionUnimplemented' extension");
247   testing_util_push_log_hook ("*property name*should not be NULL.");
248   testing_util_push_log_hook ("*property value*should*initialized GValue.");
249   testing_util_push_log_hook ("*assertion*peas_plugin_info_is_loaded*failed");
250 
251   /* Invalid GType */
252   extension = peas_engine_create_extension_with_properties (engine, info,
253                                                             G_TYPE_INVALID, 0,
254                                                             NULL, NULL);
255   g_assert (!PEAS_IS_EXTENSION (extension));
256 
257   /* GObject but not a GInterface */
258   extension = peas_engine_create_extension_with_properties (engine, info,
259                                                             PEAS_TYPE_ENGINE, 0,
260                                                             NULL, NULL);
261   g_assert (!PEAS_IS_EXTENSION (extension));
262 
263   /* Does not implement this GType */
264   extension =
265     peas_engine_create_extension_with_properties (engine, info,
266                                                   INTROSPECTION_TYPE_UNIMPLEMENTED,
267                                                   0, NULL, NULL);
268   g_assert (!PEAS_IS_EXTENSION (extension));
269 
270   /* Interface has a NULL property name*/
271   extension =
272     peas_engine_create_extension_with_properties (engine, info,
273                                                   INTROSPECTION_TYPE_CALLABLE,
274                                                   G_N_ELEMENTS (prop_names2),
275                                                   prop_names, prop_values);
276   g_assert (!PEAS_IS_EXTENSION (extension));
277 
278   /* Interface has a not initialiazed GValue */
279   extension =
280     peas_engine_create_extension_with_properties (engine, info,
281                                                   INTROSPECTION_TYPE_CALLABLE,
282                                                   G_N_ELEMENTS (prop_names2),
283                                                   prop_names2, prop_values2);
284   g_assert (!PEAS_IS_EXTENSION (extension));
285 
286   /* Not loaded */
287   g_assert (peas_engine_unload_plugin (engine, info));
288   extension =
289     peas_engine_create_extension_with_properties (engine, info,
290                                                   INTROSPECTION_TYPE_CALLABLE,
291                                                   0, NULL, NULL);
292   g_assert (!PEAS_IS_EXTENSION (extension));
293 
294   g_value_unset (&prop_values[0]);
295 
296 }
297 
298 static void
test_extension_create_with_prerequisite(PeasEngine * engine,PeasPluginInfo * info)299 test_extension_create_with_prerequisite (PeasEngine     *engine,
300                                          PeasPluginInfo *info)
301 {
302   PeasExtension *extension;
303   gint prerequisite_property = -1;
304 
305   extension = peas_engine_create_extension (engine, info,
306                                             INTROSPECTION_TYPE_HAS_PREREQUISITE,
307                                             "prerequisite-property", 47,
308                                             NULL);
309 
310   g_assert (INTROSPECTION_IS_HAS_PREREQUISITE (extension));
311   g_assert (INTROSPECTION_IS_CALLABLE (extension));
312 
313   g_object_get (extension,
314                 "prerequisite-property", &prerequisite_property,
315                 NULL);
316   g_assert_cmpint (prerequisite_property, ==, 47);
317 
318   g_object_unref (extension);
319 }
320 
321 static void
test_extension_reload(PeasEngine * engine,PeasPluginInfo * info)322 test_extension_reload (PeasEngine     *engine,
323                        PeasPluginInfo *info)
324 {
325   gint i;
326 
327   for (i = 0; i < 3; ++i)
328     {
329       g_assert (peas_engine_load_plugin (engine, info));
330       g_assert (peas_engine_unload_plugin (engine, info));
331     }
332 }
333 
334 static void
test_extension_plugin_info(PeasEngine * engine,PeasPluginInfo * info)335 test_extension_plugin_info (PeasEngine     *engine,
336                             PeasPluginInfo *info)
337 {
338   PeasExtension *extension;
339   IntrospectionBase *base;
340 
341   g_assert (peas_engine_load_plugin (engine, info));
342 
343   extension = peas_engine_create_extension (engine, info,
344                                             INTROSPECTION_TYPE_BASE,
345                                             NULL);
346 
347   base = INTROSPECTION_BASE (extension);
348 
349   g_assert (introspection_base_get_plugin_info (base) == info);
350 
351   g_object_unref (extension);
352 }
353 
354 static void
test_extension_get_settings(PeasEngine * engine,PeasPluginInfo * info)355 test_extension_get_settings (PeasEngine     *engine,
356                              PeasPluginInfo *info)
357 {
358   PeasExtension *extension;
359   IntrospectionBase *base;
360   GSettings *settings;
361 
362   g_assert (peas_engine_load_plugin (engine, info));
363 
364   extension = peas_engine_create_extension (engine, info,
365                                             INTROSPECTION_TYPE_BASE,
366                                             NULL);
367 
368   base = INTROSPECTION_BASE (extension);
369 
370   settings = introspection_base_get_settings (base);
371   g_assert (G_IS_SETTINGS (settings));
372 
373   g_object_unref (settings);
374   g_object_unref (extension);
375 }
376 
377 static void
test_extension_abstract(PeasEngine * engine,PeasPluginInfo * info)378 test_extension_abstract (PeasEngine     *engine,
379                          PeasPluginInfo *info)
380 {
381   PeasExtension *extension;
382   IntrospectionAbstract *abstract;
383 
384   g_assert (peas_engine_load_plugin (engine, info));
385 
386   extension = peas_engine_create_extension (engine, info,
387                                             INTROSPECTION_TYPE_ABSTRACT,
388                                             "abstract-property", 47,
389                                             NULL);
390 
391   abstract = INTROSPECTION_ABSTRACT (extension);
392 
393   g_assert_cmpint (introspection_abstract_get_value (abstract), ==, 47);
394   introspection_abstract_set_value (abstract, -22);
395   g_assert_cmpint (introspection_abstract_get_value (abstract), ==, -22);
396 
397   g_object_unref (extension);
398 }
399 
400 static gint
run_in_multiple_threads(GFunc func,gpointer user_data)401 run_in_multiple_threads (GFunc    func,
402                          gpointer user_data)
403 {
404   gint i, n_threads;
405   GThreadPool *pool;
406   GError *error = NULL;
407 
408   /* Avoid too many threads, but try to get some good contention */
409   n_threads = g_get_num_processors () + 2;
410 
411   pool = g_thread_pool_new (func, user_data, n_threads, TRUE, &error);
412   g_assert_no_error (error);
413 
414   for (i = 0; i < n_threads; ++i)
415     {
416       /* Cannot supply NULL as the data... */
417       g_thread_pool_push (pool, GUINT_TO_POINTER (i + 1), &error);
418       g_assert_no_error (error);
419     }
420 
421   g_thread_pool_free (pool, FALSE, TRUE);
422 
423   return n_threads;
424 }
425 
426 static void
multiple_threads_loaders_in_thread(guint nth_thread,gboolean use_nonglobal_loaders)427 multiple_threads_loaders_in_thread (guint    nth_thread,
428                                     gboolean use_nonglobal_loaders)
429 {
430   gint i, j;
431   PeasEngine *engine;
432   PeasPluginInfo *info;
433   GObject *extension;
434 
435   engine = testing_engine_new_full (use_nonglobal_loaders);
436   peas_engine_enable_loader (engine, loader);
437 
438   info = peas_engine_get_plugin_info (engine, extension_plugin);
439   g_assert (info != NULL);
440 
441   for (i = 0; i < 10; ++i)
442     {
443       g_assert (peas_engine_load_plugin (engine, info));
444 
445       for (j = 0; j < 50; ++j)
446         {
447           extension = peas_engine_create_extension (engine, info,
448                                                     INTROSPECTION_TYPE_BASE,
449                                                     NULL);
450 
451           g_assert (extension != NULL);
452           g_object_unref (extension);
453         }
454 
455       g_assert (peas_engine_unload_plugin (engine, info));
456     }
457 
458   testing_engine_free (engine);
459 }
460 
461 static void
test_extension_multiple_threads_global_loaders(PeasEngine * engine,PeasPluginInfo * info)462 test_extension_multiple_threads_global_loaders (PeasEngine     *engine,
463                                                 PeasPluginInfo *info)
464 {
465   run_in_multiple_threads ((GFunc) multiple_threads_loaders_in_thread,
466                            GINT_TO_POINTER (FALSE));
467 }
468 
469 static void
test_extension_multiple_threads_nonglobal_loaders(PeasEngine * engine,PeasPluginInfo * info)470 test_extension_multiple_threads_nonglobal_loaders (PeasEngine     *engine,
471                                                    PeasPluginInfo *info)
472 {
473   run_in_multiple_threads ((GFunc) multiple_threads_loaders_in_thread,
474                            GINT_TO_POINTER (TRUE));
475 }
476 
477 static void
multiple_threads_callbacks_in_thread(guint nth_thread,PeasActivatable * activatable)478 multiple_threads_callbacks_in_thread (guint            nth_thread,
479                                       PeasActivatable *activatable)
480 {
481   gint i;
482 
483   for (i = 0; i < 100; ++i)
484     peas_activatable_update_state (activatable);
485 }
486 
487 static void
test_extension_multiple_threads_callbacks(PeasEngine * engine,PeasPluginInfo * info)488 test_extension_multiple_threads_callbacks (PeasEngine     *engine,
489                                            PeasPluginInfo *info)
490 {
491   PeasExtension *extension;
492   gint n_threads, update_count;
493 
494   extension = peas_engine_create_extension (engine, info,
495                                             PEAS_TYPE_ACTIVATABLE,
496                                             NULL);
497 
498   n_threads = run_in_multiple_threads ((GFunc) multiple_threads_callbacks_in_thread,
499                                        extension);
500 
501   g_object_get (extension, "update-count", &update_count, NULL);
502   g_assert_cmpint (update_count, ==, n_threads * 100);
503 
504   g_object_unref (extension);
505 }
506 
507 static void
test_extension_call_no_args(PeasEngine * engine,PeasPluginInfo * info)508 test_extension_call_no_args (PeasEngine     *engine,
509                              PeasPluginInfo *info)
510 {
511   PeasExtension *extension;
512   IntrospectionCallable *callable;
513 
514   extension = peas_engine_create_extension (engine, info,
515                                             INTROSPECTION_TYPE_CALLABLE,
516                                             NULL);
517 
518   callable = INTROSPECTION_CALLABLE (extension);
519 
520   g_assert (peas_extension_call (extension, "call_no_args"));
521   introspection_callable_call_no_args (callable);
522 
523   g_object_unref (extension);
524 }
525 
526 static void
test_extension_call_with_return(PeasEngine * engine,PeasPluginInfo * info)527 test_extension_call_with_return (PeasEngine     *engine,
528                                  PeasPluginInfo *info)
529 {
530   PeasExtension *extension;
531   IntrospectionCallable *callable;
532   gchar *return_val = NULL;
533 
534   extension = peas_engine_create_extension (engine, info,
535                                             INTROSPECTION_TYPE_CALLABLE,
536                                             NULL);
537 
538   callable = INTROSPECTION_CALLABLE (extension);
539 
540   g_assert (peas_extension_call (extension, "call_with_return", &return_val));
541   g_assert_cmpstr (return_val, ==, "Hello, World!");
542 
543   g_free (return_val);
544   return_val = NULL;
545 
546   return_val = introspection_callable_call_with_return (callable);
547   g_assert_cmpstr (return_val, ==, "Hello, World!");
548 
549   g_free (return_val);
550   g_object_unref (extension);
551 }
552 
553 static void
test_extension_call_single_arg(PeasEngine * engine,PeasPluginInfo * info)554 test_extension_call_single_arg (PeasEngine     *engine,
555                                 PeasPluginInfo *info)
556 {
557   PeasExtension *extension;
558   IntrospectionCallable *callable;
559   gboolean called = FALSE;
560 
561   extension = peas_engine_create_extension (engine, info,
562                                             INTROSPECTION_TYPE_CALLABLE,
563                                             NULL);
564 
565   callable = INTROSPECTION_CALLABLE (extension);
566 
567   g_assert (peas_extension_call (extension, "call_single_arg", &called));
568   g_assert (called);
569 
570   called = FALSE;
571 
572   introspection_callable_call_single_arg (callable, &called);
573   g_assert (called);
574 
575   g_object_unref (extension);
576 }
577 
578 static void
test_extension_call_multi_args(PeasEngine * engine,PeasPluginInfo * info)579 test_extension_call_multi_args (PeasEngine     *engine,
580                                 PeasPluginInfo *info)
581 {
582   PeasExtension *extension;
583   IntrospectionCallable *callable;
584   gint in, out, inout;
585   gint inout_saved;
586 
587   extension = peas_engine_create_extension (engine, info,
588                                             INTROSPECTION_TYPE_CALLABLE,
589                                             NULL);
590 
591   callable = INTROSPECTION_CALLABLE (extension);
592 
593   in = g_random_int ();
594   inout = g_random_int ();
595   inout_saved = inout;
596 
597   g_assert (peas_extension_call (extension, "call_multi_args",
598                                  in, &out, &inout));
599 
600   g_assert_cmpint (inout_saved, ==, out);
601   g_assert_cmpint (in, ==, inout);
602 
603   in = g_random_int ();
604   inout = g_random_int ();
605   inout_saved = inout;
606 
607   introspection_callable_call_multi_args (callable, in, &out, &inout);
608 
609   g_assert_cmpint (inout_saved, ==, out);
610   g_assert_cmpint (in, ==, inout);
611 
612   g_object_unref (extension);
613 }
614 
615 static void
test_extension_call_abstract(PeasEngine * engine,PeasPluginInfo * info)616 test_extension_call_abstract (PeasEngine     *engine,
617                               PeasPluginInfo *info)
618 {
619   PeasExtension *extension;
620   gint value = 0;
621 
622   g_assert (peas_engine_load_plugin (engine, info));
623 
624   extension = peas_engine_create_extension (engine, info,
625                                             INTROSPECTION_TYPE_ABSTRACT,
626                                             "abstract-property", 47,
627                                             NULL);
628 
629   g_assert (peas_extension_call (extension, "get_value", &value));
630   g_assert_cmpint (value, ==, 47);
631 
632   g_assert (peas_extension_call (extension, "set_value", -22));
633   g_assert (peas_extension_call (extension, "get_value", &value));
634   g_assert_cmpint (value, ==, -22);
635 
636   g_object_unref (extension);
637 }
638 
639 #define _EXTENSION_TEST(loader, path, ftest) \
640   G_STMT_START { \
641     gchar *full_path = g_strdup_printf (EXTENSION_TEST_NAME (%s, "%s"), \
642                                         loader, path); \
643 \
644     g_test_add (full_path, TestFixture, \
645                 (gpointer) test_extension_##ftest, \
646                 test_setup, test_runner, test_teardown); \
647 \
648     g_free (full_path); \
649   } G_STMT_END
650 
651 void
testing_extension_basic(const gchar * loader_)652 testing_extension_basic (const gchar *loader_)
653 {
654   gint i, j;
655   gchar *loader_name;
656   PeasEngine *engine;
657 
658   loader = g_strdup (loader_);
659 
660   loader_name = g_new0 (gchar, strlen (loader) + 1);
661   for (i = 0, j = 0; loader[i] != '\0'; ++i)
662     {
663       if (loader[i] != '.')
664         loader_name[j++] = loader[i];
665     }
666 
667   extension_plugin = g_strdup_printf ("extension-%s", loader_name);
668   g_free (loader_name);
669 
670   engine = testing_engine_new ();
671   peas_engine_enable_loader (engine, loader);
672 
673   /* Check that the loaders are created lazily */
674   g_assert (g_type_from_name ("PeasPluginLoader") == G_TYPE_INVALID);
675 
676   testing_engine_free (engine);
677 
678 
679   _EXTENSION_TEST (loader, "garbage-collect", garbage_collect);
680 
681   _EXTENSION_TEST (loader, "provides-valid", provides_valid);
682   _EXTENSION_TEST (loader, "provides-invalid", provides_invalid);
683 
684   _EXTENSION_TEST (loader, "create-valid", create_valid);
685   _EXTENSION_TEST (loader, "create-valid-without-properties",
686                    create_valid_without_properties);
687   _EXTENSION_TEST (loader, "create-valid-with-properties",
688                    create_valid_with_properties);
689   _EXTENSION_TEST (loader, "create-invalid", create_invalid);
690   _EXTENSION_TEST (loader, "create-invalid-with-properties",
691                    create_invalid_with_properties);
692   _EXTENSION_TEST (loader, "create-with-prerequisite", create_with_prerequisite);
693 
694   _EXTENSION_TEST (loader, "reload", reload);
695 
696   _EXTENSION_TEST (loader, "plugin-info", plugin_info);
697   _EXTENSION_TEST (loader, "get-settings", get_settings);
698 
699   _EXTENSION_TEST (loader, "abstract", abstract);
700 
701   _EXTENSION_TEST (loader, "multiple-threads/global-loaders",
702                    multiple_threads_global_loaders);
703   _EXTENSION_TEST (loader, "multiple-threads/nonglobal-loaders",
704                    multiple_threads_nonglobal_loaders);
705 
706   /* Not needed for C plugins as they are independent of libpeas */
707   if (g_strcmp0 (loader, "c") != 0)
708     {
709       _EXTENSION_TEST (loader, "multiple-threads/callbacks",
710                        multiple_threads_callbacks);
711     }
712 }
713 
714 void
testing_extension_callable(const gchar * loader)715 testing_extension_callable (const gchar *loader)
716 {
717   _EXTENSION_TEST (loader, "call-no-args", call_no_args);
718   _EXTENSION_TEST (loader, "call-with-return", call_with_return);
719   _EXTENSION_TEST (loader, "call-single-arg", call_single_arg);
720   _EXTENSION_TEST (loader, "call-multi-args", call_multi_args);
721   _EXTENSION_TEST (loader, "call-abstract", call_abstract);
722 }
723 
724 void
testing_extension_add(const gchar * path,GTestDataFunc func)725 testing_extension_add (const gchar   *path,
726                        GTestDataFunc  func)
727 {
728   g_test_add (path, TestFixture, (gpointer) func,
729               test_setup, test_runner, test_teardown);
730 }
731 
732 int
testing_extension_run_tests(void)733 testing_extension_run_tests (void)
734 {
735   int retval;
736 
737   retval = testing_run_tests ();
738 
739   g_free (extension_plugin);
740   g_free (loader);
741 
742   return retval;
743 }
744