[libpeas] Add a test-suite



commit 06d0ab718a77a74ad365c5a9d40e05a9310a0bd5
Author: Garrett Regier <alias301 gmail com>
Date:   Fri Dec 17 12:44:33 2010 -0800

    Add a test-suite

 .gitignore                                         |    9 +
 Makefile.am                                        |    7 +-
 configure.ac                                       |   21 ++
 tests/Makefile.am                                  |   68 +++++
 tests/libpeas-gtk/Makefile.am                      |   56 ++++
 tests/libpeas-gtk/plugin-manager-store.c           |  291 +++++++++++++++++++
 tests/libpeas-gtk/plugin-manager-view.c            |  264 +++++++++++++++++
 tests/libpeas-gtk/plugin-manager.c                 |  257 +++++++++++++++++
 tests/libpeas-gtk/plugins/Makefile.am              |    1 +
 .../plugins/builtin-configurable/Makefile.am       |   21 ++
 .../builtin-configurable/builtin-configurable.c    |   75 +++++
 .../builtin-configurable/builtin-configurable.h    |   52 ++++
 .../builtin-configurable.plugin                    |    9 +
 .../plugins/builtin-configurable/builtin-plugin.c  |  149 ++++++++++
 .../plugins/builtin-configurable/builtin-plugin.h  |   55 ++++
 tests/libpeas-gtk/plugins/configurable/Makefile.am |   19 ++
 .../plugins/configurable/configurable-plugin.c     |   79 +++++
 .../plugins/configurable/configurable-plugin.h     |   55 ++++
 .../plugins/configurable/configurable.plugin       |    8 +
 tests/libpeas-gtk/testing/Makefile.am              |   21 ++
 tests/libpeas-gtk/testing/testing.c                |  222 ++++++++++++++
 tests/libpeas-gtk/testing/testing.h                |   43 +++
 tests/libpeas/Makefile.am                          |   56 ++++
 tests/libpeas/engine.c                             |  302 ++++++++++++++++++++
 tests/libpeas/extension-set.c                      |  218 ++++++++++++++
 tests/libpeas/extension.c                          |  277 ++++++++++++++++++
 tests/libpeas/introspection/Makefile.am            |   47 +++
 .../libpeas/introspection/introspection-callable.c |   93 ++++++
 .../libpeas/introspection/introspection-callable.h |   70 +++++
 .../introspection/introspection-unimplemented.c    |   39 +++
 .../introspection/introspection-unimplemented.h    |   52 ++++
 tests/libpeas/plugin-info.c                        |  191 ++++++++++++
 tests/libpeas/plugins/Makefile.am                  |    8 +
 tests/libpeas/plugins/callable-python/Makefile.am  |    7 +
 .../callable-python/callable-python-plugin.py      |   19 ++
 .../plugins/callable-python/callable-python.plugin |    8 +
 tests/libpeas/plugins/callable/Makefile.am         |   19 ++
 tests/libpeas/plugins/callable/callable-plugin.c   |  100 +++++++
 tests/libpeas/plugins/callable/callable-plugin.h   |   52 ++++
 tests/libpeas/plugins/callable/callable.plugin     |    8 +
 tests/libpeas/plugins/info-missing-iage.plugin     |    3 +
 tests/libpeas/plugins/info-missing-module.plugin   |    3 +
 tests/libpeas/plugins/info-missing-name.plugin     |    3 +
 tests/libpeas/testing/Makefile.am                  |   18 ++
 tests/libpeas/testing/testing.c                    |  146 ++++++++++
 tests/libpeas/testing/testing.h                    |   34 +++
 tests/plugins/Makefile.am                          |   12 +
 tests/plugins/builtin/Makefile.am                  |   18 ++
 tests/plugins/builtin/builtin-plugin.c             |  143 +++++++++
 tests/plugins/builtin/builtin-plugin.h             |   55 ++++
 tests/plugins/builtin/builtin.plugin               |    9 +
 tests/plugins/full-info.plugin                     |   13 +
 tests/plugins/has-dep/Makefile.am                  |   18 ++
 tests/plugins/has-dep/has-dep-plugin.c             |  143 +++++++++
 tests/plugins/has-dep/has-dep-plugin.h             |   55 ++++
 tests/plugins/has-dep/has-dep.plugin               |    9 +
 tests/plugins/loadable/Makefile.am                 |   18 ++
 tests/plugins/loadable/loadable-plugin.c           |  143 +++++++++
 tests/plugins/loadable/loadable-plugin.h           |   55 ++++
 tests/plugins/loadable/loadable.plugin             |    8 +
 tests/plugins/min-info.plugin                      |    4 +
 tests/plugins/self-dep/Makefile.am                 |   18 ++
 tests/plugins/self-dep/self-dep-plugin.c           |  143 +++++++++
 tests/plugins/self-dep/self-dep-plugin.h           |   55 ++++
 tests/plugins/self-dep/self-dep.plugin             |    9 +
 tests/plugins/unavailable.plugin                   |    9 +
 66 files changed, 4491 insertions(+), 1 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 4c8f20a..1472cab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,4 +65,13 @@ Makefile.in
 /py-compile
 /so_locations
 /stamp-h1
+/tests/*-report.html
+/tests/*-report.xml
+/tests/libpeas/engine
+/tests/libpeas/extension
+/tests/libpeas/extension-set
+/tests/libpeas/plugin-info
+/tests/libpeas-gtk/plugin-manager
+/tests/libpeas-gtk/plugin-manager-store
+/tests/libpeas-gtk/plugin-manager-view
 /xmldocs.make
diff --git a/Makefile.am b/Makefile.am
index 0cd774c..578de23 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@ if ENABLE_GTK
 SUBDIRS += libpeas-gtk peas-demo
 endif
 
-SUBDIRS += data po docs
+SUBDIRS += tests data po docs
 
 dist-hook:
 	@if test -d "$(srcdir)/.git"; \
@@ -23,3 +23,8 @@ dist-hook:
 	else \
 		echo A git clone is required to generate a ChangeLog >&2; \
 	fi
+
+test test-gdb test-report perf-report full-report: all
+	@cd tests && $(MAKE) $(AM_MAKEFLAGS) $(@)
+
+.PHONY: all test test-gdb test-report perf-report full-report
diff --git a/configure.ac b/configure.ac
index 3bd8e98..9ab1ece 100644
--- a/configure.ac
+++ b/configure.ac
@@ -261,9 +261,14 @@ AC_SUBST(LT_CURRENT)
 AC_SUBST(LT_REVISION)
 AC_SUBST(LT_AGE)
 
+# The reasons for -rpath /nowhere can be found at:
+# http://www.mail-archive.com/automake gnu org/msg10725.htm
+
 PLUGIN_LIBTOOL_FLAGS="-module -avoid-version"
+TEST_PLUGIN_LIBTOOL_FLAGS="$PLUGIN_LIBTOOL_FLAGS -rpath /nowhere"
 LOADER_LIBTOOL_FLAGS="-module -avoid-version -export-symbols-regex peas_register_types"
 AC_SUBST(PLUGIN_LIBTOOL_FLAGS)
+AC_SUBST(TEST_PLUGIN_LIBTOOL_FLAGS)
 AC_SUBST(LOADER_LIBTOOL_FLAGS)
 
 dnl ================================================================
@@ -302,6 +307,22 @@ peas-demo/plugins/pythonhello/Makefile
 peas-demo/plugins/secondtime/Makefile
 peas-demo/plugins/seedhello/Makefile
 po/Makefile.in
+tests/Makefile
+tests/libpeas/Makefile
+tests/libpeas/plugins/Makefile
+tests/libpeas/plugins/callable/Makefile
+tests/libpeas/introspection/Makefile
+tests/libpeas/testing/Makefile
+tests/libpeas-gtk/Makefile
+tests/libpeas-gtk/plugins/Makefile
+tests/libpeas-gtk/plugins/builtin-configurable/Makefile
+tests/libpeas-gtk/plugins/configurable/Makefile
+tests/libpeas-gtk/testing/Makefile
+tests/plugins/Makefile
+tests/plugins/builtin/Makefile
+tests/plugins/has-dep/Makefile
+tests/plugins/loadable/Makefile
+tests/plugins/self-dep/Makefile
 ])
 
 AC_OUTPUT
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..eea6292
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,68 @@
+SUBDIRS = plugins libpeas
+
+if ENABLE_GTK
+SUBDIRS += libpeas-gtk
+endif
+
+test test-gdb:
+	@for subdir in $(SUBDIRS) ; do \
+	   test "$$subdir" = "plugins" || \
+	   ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $(@) ) || exit $? ; \
+	 done
+
+GTESTER_REPORT = gtester-report
+
+# test-report: run tests and generate report
+# perf-report: run tests with -m perf and generate report
+# full-report: run tests with -m perf -m slow and generate report
+test-report perf-report full-report:
+	@export GTESTER_LOGDIR=`mktemp -d "$(abs_srcdir)/.testlogs-XXXXXX"` ; \
+	 if test -d "$(top_srcdir)/.git"; then \
+	   export REVISION="`git describe`" ;  \
+	 else \
+	   export REVISION="$(VERSION)" ; \
+	 fi ; \
+	 export TIMESTAMP=`date +%Y-%m-%dT%H:%M:%S%z` ; \
+	 case $@ in \
+	 test-report) test_options="-k";; \
+	 perf-report) test_options="-k -m=perf";; \
+	 full-report) test_options="-k -m=perf -m=slow";; \
+	 esac ; \
+	 echo '<?xml version="1.0"?>'              > $  xml ; \
+	 echo '<report-collection>'               >> $  xml ; \
+	 echo '<info>'                            >> $  xml ; \
+	 echo '  <package>$(PACKAGE)</package>'   >> $  xml ; \
+	 echo '  <version>$(VERSION)</version>'   >> $  xml ; \
+	 echo "  <revision>$$REVISION</revision>" >> $  xml ; \
+	 echo "  <date>$$TIMESTAMP</date>"        >> $  xml ; \
+	 echo '</info>'                           >> $  xml ; \
+	 for subdir in $(SUBDIRS) ; do \
+	   test "$$subdir" = "plugins" || { \
+	     export GTESTER_LOG=`mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ; \
+	     export GTESTER_ARGS="--verbose $$test_options -o $$GTESTER_LOG" ; \
+	     ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) generate-report ) ; \
+	     sed '1,1s/^<?xml\b[^>?]*?>//' <"$$GTESTER_LOG" >> $  xml ; \
+	   } \
+	 done ; \
+	 echo >> $  xml ; \
+	 echo '</report-collection>' >> $  xml ; \
+	 $(GTESTER_REPORT) --version 2>/dev/null 1>&2 ; test "$$?" != 0 || \
+	 $(GTESTER_REPORT) $  xml >$  html ; \
+	 rm -rf "$$GTESTER_LOGDIR" ;
+
+.PHONY: test test-gdb test-report perf-report full-report
+
+check-local: test
+
+
+HTML_REPORTS = \
+	test-report.html 	\
+	perf-report.html 	\
+	full-report.html
+
+XML_REPORTS = \
+	test-report.xml 	\
+	perf-report.xml 	\
+	full-report.xml
+
+CLEANFILES = $(HTML_REPORTS) $(XML_REPORTS)
diff --git a/tests/libpeas-gtk/Makefile.am b/tests/libpeas-gtk/Makefile.am
new file mode 100644
index 0000000..da2072c
--- /dev/null
+++ b/tests/libpeas-gtk/Makefile.am
@@ -0,0 +1,56 @@
+GTESTER = gtester
+
+TEST_PROGS =
+
+SUBDIRS = plugins testing
+
+test: $(TEST_PROGS)
+	@test -z "$(TEST_PROGS)" || \
+	 test -z "$(DISPLAY)" || \
+	 $(GTESTER) --verbose $(TEST_PROGS)
+
+test-gdb: $(TEST_PROGS)
+	@test -z "$(TEST_PROGS)" || \
+	 test -z "$(DISPLAY)" || \
+	 for test_prog in $(TEST_PROGS); do \
+	   $(GTESTER) --verbose $$test_prog || { \
+	     gdb --ex "run --verbose" ".libs/lt-$$test_prog" ; \
+	     exit 1 ; \
+	   } \
+	 done
+
+generate-report: $(TEST_PROGS)
+	@test -z "$(TEST_PROGS)" || \
+	 test -z "$(DISPLAY)" || \
+	 $(GTESTER) $(GTESTER_ARGS) $(TEST_PROGS)
+
+INCLUDES = \
+	-I$(top_srcdir)			\
+	-I$(srcdir)			\
+	$(PEAS_CFLAGS)			\
+	$(PEAS_GTK_CFLAGS)		\
+	$(WARN_CFLAGS)			\
+	$(DISABLE_DEPRECATED)
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+progs_ldadd = \
+	$(PEAS_LIBS)					\
+	$(PEAS_GTK_LIBS)				\
+	$(top_builddir)/libpeas/libpeas-1.0.la		\
+	$(top_builddir)/libpeas-gtk/libpeas-gtk-1.0.la	\
+	./testing/libtesting.la
+
+TEST_PROGS += \
+	plugin-manager		\
+	plugin-manager-store	\
+	plugin-manager-view
+
+plugin_manager_SOURCES = plugin-manager.c
+plugin_manager_LDADD   = $(progs_ldadd)
+
+plugin_manager_store_SOURCES = plugin-manager-store.c
+plugin_manager_store_LDADD   = $(progs_ldadd)
+
+plugin_manager_view_SOURCES = plugin-manager-view.c
+plugin_manager_view_LDADD   = $(progs_ldadd)
diff --git a/tests/libpeas-gtk/plugin-manager-store.c b/tests/libpeas-gtk/plugin-manager-store.c
new file mode 100644
index 0000000..38c607e
--- /dev/null
+++ b/tests/libpeas-gtk/plugin-manager-store.c
@@ -0,0 +1,291 @@
+/*
+ * plugin-manager-store.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libpeas/peas.h>
+#include <libpeas-gtk/peas-gtk.h>
+
+#include "libpeas-gtk/peas-gtk-plugin-manager-store.h"
+
+#include "testing/testing.h"
+
+typedef struct _TestFixture TestFixture;
+
+struct _TestFixture {
+  PeasEngine *engine;
+  GtkTreeView *tree_view;
+  PeasGtkPluginManagerView *view;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkListStore *store;
+};
+
+static void
+notify_model_cb (GtkTreeView *view,
+                 GParamSpec  *pspec,
+                 TestFixture *fixture)
+{
+  fixture->model = gtk_tree_view_get_model (fixture->tree_view);
+
+  if (GTK_IS_TREE_MODEL_FILTER (fixture->model))
+    {
+      GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (fixture->model);
+      fixture->store = GTK_LIST_STORE (gtk_tree_model_filter_get_model (filter));
+    }
+  else
+    {
+      fixture->store = GTK_LIST_STORE (fixture->model);
+    }
+}
+
+static void
+test_setup (TestFixture   *fixture,
+            gconstpointer  data)
+{
+  fixture->engine = testing_engine_new ();
+  fixture->tree_view = GTK_TREE_VIEW (peas_gtk_plugin_manager_view_new ());
+  fixture->view = PEAS_GTK_PLUGIN_MANAGER_VIEW (fixture->tree_view);
+  fixture->selection = gtk_tree_view_get_selection (fixture->tree_view);
+
+  g_signal_connect (fixture->view,
+                    "notify::model",
+                    G_CALLBACK (notify_model_cb),
+                    fixture);
+
+  /* Set the model, filter and store */
+  g_object_notify (G_OBJECT (fixture->tree_view), "model");
+
+  g_object_ref_sink (fixture->tree_view);
+}
+
+static void
+test_teardown (TestFixture   *fixture,
+               gconstpointer  data)
+{
+  /* Yes this really is needed */
+  g_object_run_dispose (G_OBJECT (fixture->tree_view));
+  g_object_unref (fixture->tree_view);
+
+  testing_engine_free (fixture->engine);
+}
+
+static void
+test_runner (TestFixture   *fixture,
+             gconstpointer  data)
+{
+  ((void (*) (TestFixture *)) data) (fixture);
+}
+
+static void
+test_gtk_plugin_manager_store_sorted (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info1, *info2;
+
+  /* TODO: add a plugin that would cause this to assert if strcmp() was used */
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+
+  info2 = testing_get_plugin_info_for_iter (fixture->view, &iter);
+
+  while (gtk_tree_model_iter_next (fixture->model, &iter))
+    {
+      info1 = info2;
+      info2 = testing_get_plugin_info_for_iter (fixture->view, &iter);
+      g_assert_cmpint (g_utf8_collate (peas_plugin_info_get_name (info1),
+                                       peas_plugin_info_get_name (info2)),
+                       <, 0);
+    }
+}
+
+static void
+test_gtk_plugin_manager_store_plugin_loaded (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info;
+  gboolean active;
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+  info = testing_get_plugin_info_for_iter (fixture->view, &iter);
+
+  gtk_tree_model_get (fixture->model, &iter,
+                      PEAS_GTK_PLUGIN_MANAGER_STORE_ENABLED_COLUMN, &active,
+                      -1);
+  g_assert (!active);
+
+  peas_engine_load_plugin (fixture->engine, info);
+
+  gtk_tree_model_get (fixture->model, &iter,
+                      PEAS_GTK_PLUGIN_MANAGER_STORE_ENABLED_COLUMN, &active,
+                      -1);
+  g_assert (active);
+}
+
+static void
+test_gtk_plugin_manager_store_plugin_unloaded (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info;
+  gboolean active;
+
+  test_gtk_plugin_manager_store_plugin_loaded (fixture);
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+  info = testing_get_plugin_info_for_iter (fixture->view, &iter);
+
+  peas_engine_unload_plugin (fixture->engine, info);
+
+  gtk_tree_model_get (fixture->model, &iter,
+                      PEAS_GTK_PLUGIN_MANAGER_STORE_ENABLED_COLUMN, &active,
+                      -1);
+  g_assert (!active);
+}
+
+static void
+verify_model (TestFixture    *fixture,
+              PeasPluginInfo *info,
+              gboolean        can_enable,
+              const gchar    *icon,
+              gboolean        icon_visible,
+              gboolean        info_sensitive)
+{
+  GtkTreeIter iter;
+  gboolean model_can_enable, model_icon_visible, model_info_sensitive;
+  gchar *model_icon;
+
+  testing_get_iter_for_plugin_info (fixture->view, info, &iter);
+
+  gtk_tree_model_get (fixture->model, &iter,
+    PEAS_GTK_PLUGIN_MANAGER_STORE_CAN_ENABLE_COLUMN,      &model_can_enable,
+    PEAS_GTK_PLUGIN_MANAGER_STORE_ICON_COLUMN,            &model_icon,
+    PEAS_GTK_PLUGIN_MANAGER_STORE_ICON_VISIBLE_COLUMN,    &model_icon_visible,
+    PEAS_GTK_PLUGIN_MANAGER_STORE_INFO_SENSITIVE_COLUMN,  &model_info_sensitive,
+    -1);
+
+  g_assert_cmpint (model_can_enable, ==, can_enable);
+  g_assert_cmpstr (model_icon, ==, icon);
+  g_assert_cmpint (model_icon_visible, ==, icon_visible);
+  g_assert_cmpint (model_info_sensitive, ==, info_sensitive);
+
+  g_free (model_icon);
+}
+
+static void
+test_gtk_plugin_manager_store_verify_loadable (TestFixture *fixture)
+{
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (fixture->engine, "loadable");
+
+  verify_model (fixture, info, TRUE, "libpeas-plugin", FALSE, TRUE);
+}
+
+static void
+test_gtk_plugin_manager_store_verify_unavailable (TestFixture *fixture)
+{
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (fixture->engine, "unavailable");
+
+  verify_model (fixture, info, TRUE, "libpeas-plugin", FALSE, TRUE);
+
+  peas_engine_load_plugin (fixture->engine, info);
+
+  verify_model (fixture, info, FALSE, GTK_STOCK_DIALOG_ERROR, TRUE, FALSE);
+}
+
+static void
+test_gtk_plugin_manager_store_verify_builtin (TestFixture *fixture)
+{
+  PeasPluginInfo *info;
+
+  peas_gtk_plugin_manager_view_set_show_builtin (fixture->view, TRUE);
+
+  info = peas_engine_get_plugin_info (fixture->engine, "builtin");
+
+  verify_model (fixture, info, FALSE, "libpeas-plugin", FALSE, FALSE);
+
+  peas_engine_load_plugin (fixture->engine, info);
+
+  verify_model (fixture, info, FALSE, "libpeas-plugin", FALSE, TRUE);
+}
+
+static void
+test_gtk_plugin_manager_store_verify_info (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info;
+  gchar *model_info;
+
+  /* Has description */
+  info = peas_engine_get_plugin_info (fixture->engine, "configurable");
+  testing_get_iter_for_plugin_info (fixture->view, info, &iter);
+
+  gtk_tree_model_get (fixture->model, &iter,
+    PEAS_GTK_PLUGIN_MANAGER_STORE_INFO_COLUMN,  &model_info,
+    -1);
+  g_assert_cmpstr (model_info, ==, "<b>Configurable</b>\nA plugin "
+                                   "that can be loaded and configured.");
+  g_free (model_info);
+
+  /* Does not have description */
+  info = peas_engine_get_plugin_info (fixture->engine, "min-info");
+  testing_get_iter_for_plugin_info (fixture->view, info, &iter);
+
+  gtk_tree_model_get (fixture->model, &iter,
+    PEAS_GTK_PLUGIN_MANAGER_STORE_INFO_COLUMN,  &model_info,
+    -1);
+  g_assert_cmpstr (model_info, ==, "<b>Min Info</b>");
+  g_free (model_info);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  gtk_test_init (&argc, &argv, NULL);
+
+  g_type_init ();
+
+#define TEST(path, ftest) \
+  g_test_add ("/gtk/plugin-manager-store/" path, TestFixture, \
+              (gpointer) test_gtk_plugin_manager_store_##ftest, \
+              test_setup, test_runner, test_teardown)
+
+  TEST ("sorted", sorted);
+
+  TEST ("plugin-loaded", plugin_loaded);
+  TEST ("plugin-unloaded", plugin_unloaded);
+
+  TEST ("verify-loadable", verify_loadable);
+  TEST ("verify-unavailable", verify_unavailable);
+  TEST ("verify-builtin", verify_builtin);
+  TEST ("verify-info", verify_info);
+
+#undef TEST
+
+  return g_test_run ();
+}
diff --git a/tests/libpeas-gtk/plugin-manager-view.c b/tests/libpeas-gtk/plugin-manager-view.c
new file mode 100644
index 0000000..46834da
--- /dev/null
+++ b/tests/libpeas-gtk/plugin-manager-view.c
@@ -0,0 +1,264 @@
+/*
+ * plugin-manager-view.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libpeas/peas.h>
+#include <libpeas-gtk/peas-gtk.h>
+
+#include "testing/testing.h"
+
+typedef struct _TestFixture TestFixture;
+
+struct _TestFixture {
+  PeasEngine *engine;
+  GtkTreeView *tree_view;
+  PeasGtkPluginManagerView *view;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkListStore *store;
+};
+
+static void
+notify_model_cb (GtkTreeView *view,
+                 GParamSpec  *pspec,
+                 TestFixture *fixture)
+{
+  fixture->model = gtk_tree_view_get_model (fixture->tree_view);
+
+  if (GTK_IS_TREE_MODEL_FILTER (fixture->model))
+    {
+      GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (fixture->model);
+      fixture->store = GTK_LIST_STORE (gtk_tree_model_filter_get_model (filter));
+    }
+  else
+    {
+      fixture->store = GTK_LIST_STORE (fixture->model);
+    }
+}
+
+static void
+test_setup (TestFixture   *fixture,
+            gconstpointer  data)
+{
+  fixture->engine = testing_engine_new ();
+  fixture->tree_view = GTK_TREE_VIEW (peas_gtk_plugin_manager_view_new ());
+  fixture->view = PEAS_GTK_PLUGIN_MANAGER_VIEW (fixture->tree_view);
+  fixture->selection = gtk_tree_view_get_selection (fixture->tree_view);
+
+  g_signal_connect (fixture->view,
+                    "notify::model",
+                    G_CALLBACK (notify_model_cb),
+                    fixture);
+
+  /* Set the model and store */
+  g_object_notify (G_OBJECT (fixture->tree_view), "model");
+
+  g_object_ref_sink (fixture->tree_view);
+}
+
+static void
+test_teardown (TestFixture   *fixture,
+               gconstpointer  data)
+{
+  /* Yes this really is needed */
+  g_object_run_dispose (G_OBJECT (fixture->tree_view));
+  g_object_unref (fixture->tree_view);
+
+  testing_engine_free (fixture->engine);
+}
+
+static void
+test_runner (TestFixture   *fixture,
+             gconstpointer  data)
+{
+  ((void (*) (TestFixture *)) data) (fixture);
+}
+
+/* Based on code from peas-gtk-manager-view.h */
+static void
+convert_iter_to_child_iter (PeasGtkPluginManagerView *view,
+                            GtkTreeIter              *iter)
+{
+  GtkTreeModel *model;
+  GtkTreeIter child_iter;
+
+  if (peas_gtk_plugin_manager_view_get_show_builtin (view))
+    return;
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+
+  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
+                                                    &child_iter, iter);
+
+  *iter = child_iter;
+}
+
+static gboolean
+model_has_builtin (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  gboolean found = FALSE;
+
+  if (gtk_tree_model_get_iter_first (fixture->model, &iter))
+    {
+      do
+        {
+          if (peas_plugin_info_is_builtin (testing_get_plugin_info_for_iter (fixture->view, &iter)))
+            found = TRUE;
+        }
+      while (!found && gtk_tree_model_iter_next (fixture->model, &iter));
+    }
+
+  return found;
+}
+
+static void
+test_gtk_plugin_manager_view_selection (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info;
+
+  info = peas_gtk_plugin_manager_view_get_selected_plugin (fixture->view);
+  g_assert (info == NULL);
+
+  gtk_tree_model_get_iter_first (fixture->model, &iter);
+
+  gtk_tree_selection_select_iter (fixture->selection, &iter);
+
+  info = peas_gtk_plugin_manager_view_get_selected_plugin (fixture->view);
+  g_assert (info != NULL);
+}
+
+static void
+test_gtk_plugin_manager_view_show_builtin (TestFixture *fixture)
+{
+  peas_gtk_plugin_manager_view_set_show_builtin (fixture->view, TRUE);
+
+  g_assert (model_has_builtin (fixture));
+}
+
+static void
+test_gtk_plugin_manager_view_hide_builtin (TestFixture *fixture)
+{
+  /* Should this be here given its already the default? */
+  peas_gtk_plugin_manager_view_set_show_builtin (fixture->view, FALSE);
+
+  g_assert (!model_has_builtin (fixture));
+}
+
+static void
+test_gtk_plugin_manager_view_reload (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *removed_info, *selected_info;
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+  gtk_tree_selection_select_iter (fixture->selection, &iter);
+  removed_info = testing_get_plugin_info_for_iter (fixture->view, &iter);
+
+  convert_iter_to_child_iter (fixture->view, &iter);
+  gtk_list_store_remove (fixture->store, &iter);
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+  gtk_tree_selection_select_iter (fixture->selection, &iter);
+  selected_info = testing_get_plugin_info_for_iter (fixture->view, &iter);
+
+  peas_engine_rescan_plugins (fixture->engine);
+
+  g_assert (gtk_tree_selection_get_selected (fixture->selection, NULL, &iter));
+  g_assert (testing_get_plugin_info_for_iter (fixture->view, &iter) == selected_info);
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+  g_assert (testing_get_plugin_info_for_iter (fixture->view, &iter) == removed_info);
+}
+
+static void
+test_gtk_plugin_manager_view_enable_plugin (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  GtkTreePath *path;
+  GtkTreeViewColumn *column;
+  PeasPluginInfo *info;
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+  info = testing_get_plugin_info_for_iter (fixture->view, &iter);
+  path = gtk_tree_model_get_path (fixture->model, &iter);
+  column = gtk_tree_view_get_column (fixture->tree_view, 0);
+
+  g_assert (!peas_plugin_info_is_loaded (info));
+  gtk_tree_view_row_activated (fixture->tree_view, path, column);
+  g_assert (peas_plugin_info_is_loaded (info));
+}
+
+static void
+test_gtk_plugin_manager_view_enable_builtin_plugin (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  GtkTreePath *path;
+  GtkTreeViewColumn *column;
+  PeasPluginInfo *info;
+
+  peas_gtk_plugin_manager_view_set_show_builtin (fixture->view, TRUE);
+
+  info = peas_engine_get_plugin_info (fixture->engine, "builtin");
+
+  testing_get_iter_for_plugin_info (fixture->view, info, &iter);
+
+  path = gtk_tree_model_get_path (fixture->model, &iter);
+  column = gtk_tree_view_get_column (fixture->tree_view, 0);
+
+  g_assert (!peas_plugin_info_is_loaded (info));
+  gtk_tree_view_row_activated (fixture->tree_view, path, column);
+  g_assert (!peas_plugin_info_is_loaded (info));
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  gtk_test_init (&argc, &argv, NULL);
+
+  g_type_init ();
+
+#define TEST(path, ftest) \
+  g_test_add ("/gtk/plugin-manager-view/" path, TestFixture, \
+              (gpointer) test_gtk_plugin_manager_view_##ftest, \
+              test_setup, test_runner, test_teardown)
+
+  TEST ("selection", selection);
+
+  TEST ("show-builtin", show_builtin);
+  TEST ("hide-builtin", hide_builtin);
+
+  TEST ("reload", reload);
+
+  TEST ("enable-plugin", enable_plugin);
+  TEST ("enable-builtin-plugin", enable_builtin_plugin);
+
+#undef TEST
+
+  return g_test_run ();
+}
diff --git a/tests/libpeas-gtk/plugin-manager.c b/tests/libpeas-gtk/plugin-manager.c
new file mode 100644
index 0000000..45f2bf0
--- /dev/null
+++ b/tests/libpeas-gtk/plugin-manager.c
@@ -0,0 +1,257 @@
+/*
+ * plugin-manager.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libpeas/peas.h>
+#include <libpeas-gtk/peas-gtk.h>
+
+#include "testing/testing.h"
+
+typedef struct _TestFixture TestFixture;
+
+struct _TestFixture {
+  PeasEngine *engine;
+  PeasGtkPluginManager *manager;
+  PeasGtkPluginManagerView *view;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkWidget *about_button;
+  GtkWidget *configure_button;
+};
+
+static void
+notify_model_cb (GtkTreeView *view,
+                 GParamSpec  *pspec,
+                 TestFixture *fixture)
+{
+  fixture->model = gtk_tree_view_get_model (GTK_TREE_VIEW (fixture->view));
+}
+
+static void
+plugin_manager_forall_cb (GtkWidget  *widget,
+                          GtkWidget **button_box)
+{
+  if (GTK_IS_BUTTON_BOX (widget))
+    *button_box = widget;
+}
+
+static void
+test_setup (TestFixture   *fixture,
+            gconstpointer  data)
+{
+  GList *buttons;
+  GList *button;
+  GtkContainer *button_box = NULL;
+
+  fixture->engine = testing_engine_new ();
+  fixture->manager = PEAS_GTK_PLUGIN_MANAGER (peas_gtk_plugin_manager_new ());
+  fixture->view = PEAS_GTK_PLUGIN_MANAGER_VIEW (peas_gtk_plugin_manager_get_view (fixture->manager));
+  fixture->selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (fixture->view));
+
+  g_signal_connect (fixture->view,
+                    "notify::model",
+                    G_CALLBACK (notify_model_cb),
+                    fixture);
+
+  /* Set the model */
+  g_object_notify (G_OBJECT (fixture->view), "model");
+
+  /* Must use forall at the buttons are "internal" children */
+  gtk_container_forall (GTK_CONTAINER (fixture->manager),
+                        (GtkCallback) plugin_manager_forall_cb,
+                        &button_box);
+
+  g_assert (button_box != NULL);
+
+  buttons = gtk_container_get_children (button_box);
+
+  for (button = buttons; button != NULL; button = button->next)
+    {
+      if (GTK_IS_BUTTON (button->data))
+        {
+          const gchar *label = gtk_button_get_label (GTK_BUTTON (button->data));
+
+          if (g_strcmp0 (label, GTK_STOCK_ABOUT) == 0)
+            fixture->about_button = GTK_WIDGET (button->data);
+          else if (g_strcmp0 (label, GTK_STOCK_PREFERENCES) == 0)
+            fixture->configure_button = GTK_WIDGET (button->data);
+        }
+    }
+
+  g_assert (fixture->about_button != NULL);
+  g_assert (fixture->configure_button != NULL);
+
+  g_list_free (buttons);
+
+  g_object_ref_sink (fixture->manager);
+}
+
+static void
+test_teardown (TestFixture   *fixture,
+               gconstpointer  data)
+{
+  /* Yes this really is needed */
+  g_object_run_dispose (G_OBJECT (fixture->manager));
+  g_object_unref (fixture->manager);
+
+  testing_engine_free (fixture->engine);
+}
+
+static void
+test_runner (TestFixture   *fixture,
+             gconstpointer  data)
+{
+  ((void (*) (TestFixture *)) data) (fixture);
+}
+
+static void
+test_gtk_plugin_manager_about_button_sensitivity (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info;
+
+  /* Must come first otherwise the first iter may
+   * be after a revealed builtin plugin
+   */
+  peas_gtk_plugin_manager_view_set_show_builtin (fixture->view, TRUE);
+
+  /* Causes the plugin to become unavailable */
+  info = peas_engine_get_plugin_info (fixture->engine, "unavailable");
+  peas_engine_load_plugin (fixture->engine, info);
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+
+  do
+    {
+      gtk_tree_selection_select_iter (fixture->selection, &iter);
+
+      g_assert (gtk_widget_get_sensitive (fixture->about_button));
+    }
+  while (gtk_tree_model_iter_next (fixture->model, &iter));
+}
+
+static void
+test_gtk_plugin_manager_configure_button_sensitivity (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info;
+
+  /* Must come first otherwise the first iter may
+   * be after a revealed builtin plugin
+   */
+  peas_gtk_plugin_manager_view_set_show_builtin (fixture->view, TRUE);
+
+  /* So we can configure them */
+  info = peas_engine_get_plugin_info (fixture->engine, "builtin-configurable");
+  peas_engine_load_plugin (fixture->engine, info);
+  info = peas_engine_get_plugin_info (fixture->engine, "configurable");
+  peas_engine_load_plugin (fixture->engine, info);
+
+  /* Causes the plugin to become unavailable */
+  info = peas_engine_get_plugin_info (fixture->engine, "unavailable");
+  peas_engine_load_plugin (fixture->engine, info);
+
+  g_assert (gtk_tree_model_get_iter_first (fixture->model, &iter));
+
+  do
+    {
+      gboolean sensitive;
+
+      gtk_tree_selection_select_iter (fixture->selection, &iter);
+
+      info = testing_get_plugin_info_for_iter (fixture->view, &iter);
+
+      if (!peas_plugin_info_is_loaded (info))
+        {
+          sensitive = FALSE;
+        }
+      else
+        {
+          sensitive = peas_engine_provides_extension (fixture->engine, info,
+                                                      PEAS_GTK_TYPE_CONFIGURABLE);
+        }
+
+      g_assert_cmpint (gtk_widget_get_sensitive (fixture->configure_button),
+                       ==, sensitive);
+    }
+  while (gtk_tree_model_iter_next (fixture->model, &iter));
+}
+
+static void
+test_gtk_plugin_manager_plugin_loaded (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (fixture->engine, "configurable");
+  testing_get_iter_for_plugin_info (fixture->view, info, &iter);
+
+  gtk_tree_selection_select_iter (fixture->selection, &iter);
+
+  g_assert (!gtk_widget_is_sensitive (fixture->configure_button));
+  peas_engine_load_plugin (fixture->engine, info);
+  g_assert (gtk_widget_is_sensitive (fixture->configure_button));
+}
+
+static void
+test_gtk_plugin_manager_plugin_unloaded (TestFixture *fixture)
+{
+  GtkTreeIter iter;
+  PeasPluginInfo *info;
+
+  test_gtk_plugin_manager_plugin_loaded (fixture);
+
+  info = peas_engine_get_plugin_info (fixture->engine, "configurable");
+  testing_get_iter_for_plugin_info (fixture->view, info, &iter);
+
+  g_assert (gtk_widget_is_sensitive (fixture->configure_button));
+  peas_engine_unload_plugin (fixture->engine, info);
+  g_assert (!gtk_widget_is_sensitive (fixture->configure_button));
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  gtk_test_init (&argc, &argv, NULL);
+
+  g_type_init ();
+
+#define TEST(path, ftest) \
+  g_test_add ("/gtk/plugin-manager/" path, TestFixture, \
+              (gpointer) test_gtk_plugin_manager_##ftest, \
+              test_setup, test_runner, test_teardown)
+
+  TEST ("about-button-sensitivity", about_button_sensitivity);
+  TEST ("configure-button-sensitivity", configure_button_sensitivity);
+
+  TEST ("plugin-loaded", plugin_loaded);
+  TEST ("plugin-unloaded", plugin_unloaded);
+
+#undef TEST
+
+  return g_test_run ();
+}
diff --git a/tests/libpeas-gtk/plugins/Makefile.am b/tests/libpeas-gtk/plugins/Makefile.am
new file mode 100644
index 0000000..dfa90bf
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = builtin-configurable configurable
diff --git a/tests/libpeas-gtk/plugins/builtin-configurable/Makefile.am b/tests/libpeas-gtk/plugins/builtin-configurable/Makefile.am
new file mode 100644
index 0000000..453e37d
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/builtin-configurable/Makefile.am
@@ -0,0 +1,21 @@
+INCLUDES = \
+	-I$(top_srcdir)		\
+	$(PEAS_CFLAGS)		\
+	$(PEAS_GTK_CFLAGS)	\
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+noinst_LTLIBRARIES = libbuiltin-configurable.la
+
+libbuiltin_configurable_la_SOURCES = \
+	builtin-plugin.c	\
+	builtin-plugin.h	\
+	builtin-configurable.c	\
+	builtin-configurable.h
+
+libbuiltin_configurable_la_LDFLAGS = $(TEST_PLUGIN_LIBTOOL_FLAGS)
+libbuiltin_configurable_la_LIBADD  = $(PEAS_LIBS) $(PEAS_GTK_LIBS)
+
+noinst_DATA = builtin-configurable.plugin
+
+EXTRA_DIST = $(noinst_DATA)
diff --git a/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.c b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.c
new file mode 100644
index 0000000..5a14996
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.c
@@ -0,0 +1,75 @@
+/*
+ * builtin-configurable.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <libpeas/peas.h>
+#include <libpeas-gtk/peas-gtk.h>
+
+#include "builtin-configurable.h"
+
+static void peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingBuiltinConfigurable,
+                                testing_builtin_configurable,
+                                PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_GTK_TYPE_CONFIGURABLE,
+                                                               peas_gtk_configurable_iface_init))
+
+static void
+testing_builtin_configurable_init (TestingBuiltinConfigurable *configurable)
+{
+}
+
+static void
+testing_builtin_configurable_class_init (TestingBuiltinConfigurableClass *klass)
+{
+}
+
+static GtkWidget *
+testing_builtin_create_configure_widget (PeasGtkConfigurable *configurable)
+{
+  return gtk_label_new ("Hello, World!");
+}
+
+static void
+peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface)
+{
+  iface->create_configure_widget = testing_builtin_create_configure_widget;
+}
+
+static void
+testing_builtin_configurable_class_finalize (TestingBuiltinConfigurableClass *klass)
+{
+}
+
+void
+testing_builtin_configurable_register (GTypeModule *module)
+{
+  testing_builtin_configurable_register_type (module);
+}
diff --git a/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.h b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.h
new file mode 100644
index 0000000..cedc294
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.h
@@ -0,0 +1,52 @@
+/*
+ * builtin-configurable.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_BUILTIN_CONFIGURABLE_H__
+#define __TESTING_BUILTIN_CONFIGURABLE_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_BUILTIN_CONFIGURABLE         (testing_builtin_configurable_get_type ())
+#define TESTING_BUILTIN_CONFIGURABLE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_BUILTIN_CONFIGURABLE, TestingBuiltinConfigurable))
+#define TESTING_BUILTIN_CONFIGURABLE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_BUILTIN_CONFIGURABLE, TestingBuiltinConfigurable))
+#define TESTING_IS_BUILTIN_CONFIGURABLE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_BUILTIN_CONFIGURABLE))
+#define TESTING_IS_BUILTIN_CONFIGURABLE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_BUILTIN_CONFIGURABLE))
+#define TESTING_BUILTIN_CONFIGURABLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_BUILTIN_CONFIGURABLE, TestingBuiltinConfigurableClass))
+
+typedef struct _TestingBuiltinConfigurable         TestingBuiltinConfigurable;
+typedef struct _TestingBuiltinConfigurableClass    TestingBuiltinConfigurableClass;
+
+struct _TestingBuiltinConfigurable {
+  PeasExtensionBase parent_instance;
+};
+
+struct _TestingBuiltinConfigurableClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+GType testing_builtin_configurable_get_type (void) G_GNUC_CONST;
+void  testing_builtin_configurable_register (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_BUILTIN_CONFIGURABLE_H__ */
diff --git a/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.plugin b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.plugin
new file mode 100644
index 0000000..574dd69
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-configurable.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=builtin-configurable
+IAge=2
+Name=Builtin Configurable
+Description=A plugin that can be loaded, is builtin and configurable.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
+Builtin=true
diff --git a/tests/libpeas-gtk/plugins/builtin-configurable/builtin-plugin.c b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-plugin.c
new file mode 100644
index 0000000..8250fc8
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-plugin.c
@@ -0,0 +1,149 @@
+/*
+ * builtin-plugin.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <libpeas/peas.h>
+#include <libpeas-gtk/peas-gtk.h>
+
+#include "builtin-plugin.h"
+#include "builtin-configurable.h"
+
+struct _TestingBuiltinPluginPrivate {
+  GObject *object;
+};
+
+static void peas_activatable_iface_init (PeasActivatableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingBuiltinPlugin,
+                                testing_builtin_plugin,
+                                PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_TYPE_ACTIVATABLE,
+                                                               peas_activatable_iface_init))
+
+enum {
+  PROP_0,
+  PROP_OBJECT
+};
+
+static void
+testing_builtin_plugin_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  TestingBuiltinPlugin *plugin = TESTING_BUILTIN_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      plugin->priv->object = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_builtin_plugin_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  TestingBuiltinPlugin *plugin = TESTING_BUILTIN_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      g_value_set_object (value, plugin->priv->object);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_builtin_plugin_init (TestingBuiltinPlugin *plugin)
+{
+  plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin,
+                                              TESTING_TYPE_BUILTIN_PLUGIN,
+                                              TestingBuiltinPluginPrivate);
+}
+
+static void
+testing_builtin_plugin_activate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_builtin_plugin_deactivate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_builtin_plugin_class_init (TestingBuiltinPluginClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = testing_builtin_plugin_set_property;
+  object_class->get_property = testing_builtin_plugin_get_property;
+
+  g_object_class_override_property (object_class, PROP_OBJECT, "object");
+
+  g_type_class_add_private (klass, sizeof (TestingBuiltinPluginPrivate));
+}
+
+static void
+peas_activatable_iface_init (PeasActivatableInterface *iface)
+{
+  iface->activate = testing_builtin_plugin_activate;
+  iface->deactivate = testing_builtin_plugin_deactivate;
+}
+
+static void
+testing_builtin_plugin_class_finalize (TestingBuiltinPluginClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+  testing_builtin_plugin_register_type (G_TYPE_MODULE (module));
+  testing_builtin_configurable_register (G_TYPE_MODULE (module));
+
+  peas_object_module_register_extension_type (module,
+                                              PEAS_TYPE_ACTIVATABLE,
+                                              TESTING_TYPE_BUILTIN_PLUGIN);
+  peas_object_module_register_extension_type (module,
+                                              PEAS_GTK_TYPE_CONFIGURABLE,
+                                              TESTING_TYPE_BUILTIN_CONFIGURABLE);
+}
diff --git a/tests/libpeas-gtk/plugins/builtin-configurable/builtin-plugin.h b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-plugin.h
new file mode 100644
index 0000000..5eefda5
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/builtin-configurable/builtin-plugin.h
@@ -0,0 +1,55 @@
+/*
+ * builtin-plugin.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_BUILTIN_PLUGIN_H__
+#define __TESTING_BUILTIN_PLUGIN_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_BUILTIN_PLUGIN         (testing_builtin_plugin_get_type ())
+#define TESTING_BUILTIN_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_BUILTIN_PLUGIN, TestingBuiltinPlugin))
+#define TESTING_BUILTIN_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_BUILTIN_PLUGIN, TestingBuiltinPlugin))
+#define TESTING_IS_BUILTIN_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_BUILTIN_PLUGIN))
+#define TESTING_IS_BUILTIN_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_BUILTIN_PLUGIN))
+#define TESTING_BUILTIN_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_BUILTIN_PLUGIN, TestingBuiltinPluginClass))
+
+typedef struct _TestingBuiltinPlugin         TestingBuiltinPlugin;
+typedef struct _TestingBuiltinPluginClass    TestingBuiltinPluginClass;
+typedef struct _TestingBuiltinPluginPrivate  TestingBuiltinPluginPrivate;
+
+struct _TestingBuiltinPlugin {
+  PeasExtensionBase parent_instance;
+
+  TestingBuiltinPluginPrivate *priv;
+};
+
+struct _TestingBuiltinPluginClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+GType                 testing_builtin_plugin_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void  peas_register_types             (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_BUILTIN_PLUGIN_H__ */
diff --git a/tests/libpeas-gtk/plugins/configurable/Makefile.am b/tests/libpeas-gtk/plugins/configurable/Makefile.am
new file mode 100644
index 0000000..11acca9
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/configurable/Makefile.am
@@ -0,0 +1,19 @@
+INCLUDES = \
+	-I$(top_srcdir)		\
+	$(PEAS_CFLAGS)		\
+	$(PEAS_GTK_CFLAGS)	\
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+noinst_LTLIBRARIES = libconfigurable.la
+
+libconfigurable_la_SOURCES = \
+	configurable-plugin.c	\
+	configurable-plugin.h
+
+libconfigurable_la_LDFLAGS = $(TEST_PLUGIN_LIBTOOL_FLAGS)
+libconfigurable_la_LIBADD  = $(PEAS_LIBS) $(PEAS_GTK_LIBS)
+
+noinst_DATA = configurable.plugin
+
+noinst_DIST = $(noinst_DATA)
diff --git a/tests/libpeas-gtk/plugins/configurable/configurable-plugin.c b/tests/libpeas-gtk/plugins/configurable/configurable-plugin.c
new file mode 100644
index 0000000..6444c1b
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/configurable/configurable-plugin.c
@@ -0,0 +1,79 @@
+/*
+ * configurable-plugin.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <libpeas/peas.h>
+#include <libpeas-gtk/peas-gtk.h>
+
+#include "configurable-plugin.h"
+
+static void peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingConfigurablePlugin,
+                                testing_configurable_plugin,
+                                PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_GTK_TYPE_CONFIGURABLE,
+                                                               peas_gtk_configurable_iface_init))
+
+static void
+testing_configurable_plugin_init (TestingConfigurablePlugin *configurable)
+{
+}
+
+static void
+testing_configurable_plugin_class_init (TestingConfigurablePluginClass *klass)
+{
+}
+
+static GtkWidget *
+testing_configurable_plugin_create_configure_widget (PeasGtkConfigurable *configurable)
+{
+  return gtk_label_new ("Hello, World!");
+}
+
+static void
+peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface)
+{
+  iface->create_configure_widget = testing_configurable_plugin_create_configure_widget;
+}
+
+static void
+testing_configurable_plugin_class_finalize (TestingConfigurablePluginClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+  testing_configurable_plugin_register_type (G_TYPE_MODULE (module));
+
+  peas_object_module_register_extension_type (module,
+                                              PEAS_GTK_TYPE_CONFIGURABLE,
+                                              TESTING_TYPE_CONFIGURABLE_PLUGIN);
+}
diff --git a/tests/libpeas-gtk/plugins/configurable/configurable-plugin.h b/tests/libpeas-gtk/plugins/configurable/configurable-plugin.h
new file mode 100644
index 0000000..d1d4eef
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/configurable/configurable-plugin.h
@@ -0,0 +1,55 @@
+/*
+ * configurable-plugin.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_CONFIGURABLE_PLUGIN_H__
+#define __TESTING_CONFIGURABLE_PLUGIN_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_CONFIGURABLE_PLUGIN         (testing_configurable_plugin_get_type ())
+#define TESTING_CONFIGURABLE_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_CONFIGURABLE_PLUGIN, TestingConfigurablePlugin))
+#define TESTING_CONFIGURABLE_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_CONFIGURABLE_PLUGIN, TestingConfigurablePlugin))
+#define TESTING_IS_CONFIGURABLE_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_CONFIGURABLE_PLUGIN))
+#define TESTING_IS_CONFIGURABLE_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_CONFIGURABLE_PLUGIN))
+#define TESTING_CONFIGURABLE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_CONFIGURABLE_PLUGIN, TestingConfigurablePluginClass))
+
+typedef struct _TestingConfigurablePlugin         TestingConfigurablePlugin;
+typedef struct _TestingConfigurablePluginClass    TestingConfigurablePluginClass;
+typedef struct _TestingConfigurablePluginPrivate  TestingConfigurablePluginPrivate;
+
+struct _TestingConfigurablePlugin {
+  PeasExtensionBase parent_instance;
+
+  TestingConfigurablePluginPrivate *priv;
+};
+
+struct _TestingConfigurablePluginClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+GType                 testing_configurable_plugin_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void  peas_register_types                  (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_CONFIGURABLE_PLUGIN_H__ */
diff --git a/tests/libpeas-gtk/plugins/configurable/configurable.plugin b/tests/libpeas-gtk/plugins/configurable/configurable.plugin
new file mode 100644
index 0000000..07e9864
--- /dev/null
+++ b/tests/libpeas-gtk/plugins/configurable/configurable.plugin
@@ -0,0 +1,8 @@
+[Plugin]
+Module=configurable
+IAge=2
+Name=Configurable
+Description=A plugin that can be loaded and configured.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
diff --git a/tests/libpeas-gtk/testing/Makefile.am b/tests/libpeas-gtk/testing/Makefile.am
new file mode 100644
index 0000000..117a1ac
--- /dev/null
+++ b/tests/libpeas-gtk/testing/Makefile.am
@@ -0,0 +1,21 @@
+noinst_LTLIBRARIES = libtesting.la
+
+INCLUDES = \
+	-I$(top_srcdir)				\
+	-I$(srcdir)				\
+	$(PEAS_CFLAGS)				\
+	$(PEAS_GTK_CFLAGS)			\
+	$(WARN_CFLAGS)				\
+	$(DISABLE_DEPRECATED)			\
+	-DBUILDDIR="\"$(abs_top_builddir)\""
+
+libtesting_la_LDFLAGS = \
+	-export-dynamic -no-undefined -export-symbols-regex "^[^_].*"
+
+libtesting_la_LIBADD = \
+	$(PEAS_LIBS)					\
+	$(PEAS_GTK_LIBS)				\
+	$(top_builddir)/libpeas/libpeas-1.0.la		\
+	$(top_builddir)/libpeas-gtk/libpeas-gtk-1.0.la
+
+libtesting_la_SOURCES = testing.c testing.h
diff --git a/tests/libpeas-gtk/testing/testing.c b/tests/libpeas-gtk/testing/testing.c
new file mode 100644
index 0000000..71e9539
--- /dev/null
+++ b/tests/libpeas-gtk/testing/testing.c
@@ -0,0 +1,222 @@
+/*
+ * testing.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <girepository.h>
+
+#include "libpeas/peas-plugin-info-priv.h"
+
+#include "testing.h"
+
+static GLogFunc default_log_func;
+
+/* These are warning that just have to happen for testing
+ * purposes and as such we don't want to abort on them.
+ *
+ * Would be nice if we could assert that they were...
+ */
+static const gchar *allowed_patterns[] = {
+  "*Plugin not found: does-not-exist*",
+  "*libcloader.so*cannot open shared object file: No such file or directory*",
+};
+
+static void
+log_handler (const gchar    *log_domain,
+             GLogLevelFlags  log_level,
+             const gchar    *message,
+             gpointer        user_data)
+{
+  gint i;
+
+  if ((log_level & G_LOG_LEVEL_DEBUG) != 0 ||
+      (log_level & G_LOG_LEVEL_INFO) != 0 ||
+      (log_level & G_LOG_LEVEL_MESSAGE) != 0)
+    {
+      default_log_func (log_domain, log_level, message, user_data);
+      return;
+    }
+
+  if ((log_level & G_LOG_LEVEL_CRITICAL) != 0 ||
+      (log_level & G_LOG_LEVEL_ERROR) != 0)
+    {
+      goto out;
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (allowed_patterns); ++i)
+    {
+      if (g_pattern_match_simple (allowed_patterns[i], message))
+        return;
+    }
+
+out:
+
+  default_log_func (log_domain, log_level, message, user_data);
+
+  /* Make sure we abort for warnings */
+  abort ();
+}
+
+PeasEngine *
+testing_engine_new (void)
+{
+  PeasEngine *engine;
+  GError *error = NULL;
+  static gboolean initialized = FALSE;
+
+  if (initialized)
+    return peas_engine_get_default ();
+
+  /* Don't always abort on warnings */
+  g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
+
+  default_log_func = g_log_set_default_handler (log_handler, NULL);
+
+  g_irepository_prepend_search_path (BUILDDIR "/libpeas");
+  g_irepository_prepend_search_path (BUILDDIR "/libpeas-gtk");
+
+  g_setenv ("PEAS_PLUGIN_LOADERS_DIR", BUILDDIR "/loaders", TRUE);
+
+  g_irepository_require (g_irepository_get_default (), "Peas", "1.0", 0, &error);
+  g_assert_no_error (error);
+  g_irepository_require (g_irepository_get_default (), "PeasGtk", "1.0", 0, &error);
+  g_assert_no_error (error);
+
+  /* Must be after requiring typelibs */
+  engine = peas_engine_get_default ();
+
+  peas_engine_add_search_path (engine, BUILDDIR "/tests/plugins", NULL);
+  peas_engine_add_search_path (engine, BUILDDIR "/tests/libpeas-gtk/plugins", NULL);
+  peas_engine_rescan_plugins (engine);
+
+  initialized = TRUE;
+
+  return engine;
+}
+
+void
+testing_engine_free (PeasEngine *engine)
+{
+  const GList *plugins;
+
+  /* This causes errors during the next test:
+  g_object_unref (engine);*/
+
+  /* Otherwise the tests may cause each other to fail
+   * because they expected a plugin to be available
+   * but it failed loading making it unavailable
+   */
+  plugins = peas_engine_get_plugin_list (engine);
+  for (; plugins != NULL; plugins = plugins->next)
+    ((PeasPluginInfo *) plugins->data)->available = TRUE;
+
+  peas_engine_set_loaded_plugins (engine, NULL);
+  g_assert (peas_engine_get_loaded_plugins (engine) == NULL);
+}
+
+PeasPluginInfo *
+testing_get_plugin_info_for_iter (PeasGtkPluginManagerView *view,
+                                  GtkTreeIter              *iter)
+{
+  GtkTreeSelection *selection;
+  GtkTreeIter selected_iter;
+  gboolean had_selection;
+  PeasPluginInfo *info;
+
+  /* This is annoying but the only way to get the plugin info
+   * is to ask the view for the info of the selected plugin
+   */
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+
+  had_selection = gtk_tree_selection_get_selected (selection,
+                                                   NULL, &selected_iter);
+
+  gtk_tree_selection_select_iter (selection, iter);
+
+  info = peas_gtk_plugin_manager_view_get_selected_plugin (view);
+
+  if (had_selection)
+    gtk_tree_selection_select_iter (selection, &selected_iter);
+
+  return info;
+}
+
+void
+testing_get_iter_for_plugin_info (PeasGtkPluginManagerView *view,
+                                  PeasPluginInfo           *info,
+                                  GtkTreeIter              *iter)
+{
+  GtkTreeModel *model;
+  gboolean found = FALSE;
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+
+  g_assert (gtk_tree_model_get_iter_first (model, iter));
+
+  do
+    {
+      if (testing_get_plugin_info_for_iter (view, iter) == info)
+        found = TRUE;
+    }
+  while (!found && gtk_tree_model_iter_next (model, iter));
+
+  g_assert (found);
+}
+
+static gboolean
+delete_event_cb (GtkWidget *window,
+                 GdkEvent  *event,
+                 GtkWidget *widget)
+{
+  gtk_main_quit ();
+
+  return TRUE;
+}
+
+/* This takes a gpointer for ease of debugging */
+void
+testing_show_widget (gpointer widget)
+{
+  GtkWidget *window;
+
+  g_assert (GTK_IS_WIDGET (widget));
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_has_resize_grip (GTK_WINDOW (window), FALSE);
+  gtk_window_set_default_size (GTK_WINDOW (window), 200, 100);
+
+  gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (widget));
+
+  gtk_widget_show_all (window);
+
+  g_signal_connect (window,
+                    "delete-event",
+                    G_CALLBACK (delete_event_cb),
+                    widget);
+
+  gtk_main ();
+}
diff --git a/tests/libpeas-gtk/testing/testing.h b/tests/libpeas-gtk/testing/testing.h
new file mode 100644
index 0000000..f5d9d0c
--- /dev/null
+++ b/tests/libpeas-gtk/testing/testing.h
@@ -0,0 +1,43 @@
+/*
+ * testing.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_H__
+#define __TESTING_H__
+
+#include <libpeas/peas.h>
+#include <libpeas-gtk/peas-gtk.h>
+
+G_BEGIN_DECLS
+
+PeasEngine     *testing_engine_new               (void);
+void            testing_engine_free              (PeasEngine *engine);
+
+PeasPluginInfo *testing_get_plugin_info_for_iter (PeasGtkPluginManagerView *view,
+                                                  GtkTreeIter              *iter);
+void            testing_get_iter_for_plugin_info (PeasGtkPluginManagerView *view,
+                                                  PeasPluginInfo           *info,
+                                                  GtkTreeIter              *iter);
+
+void            testing_show_widget              (gpointer                  widget);
+
+G_END_DECLS
+
+#endif /* __TESTING_H__ */
diff --git a/tests/libpeas/Makefile.am b/tests/libpeas/Makefile.am
new file mode 100644
index 0000000..3178c13
--- /dev/null
+++ b/tests/libpeas/Makefile.am
@@ -0,0 +1,56 @@
+GTESTER = gtester
+
+TEST_PROGS =
+
+SUBDIRS = introspection plugins testing
+
+test: $(TEST_PROGS)
+	@test -z "$(TEST_PROGS)" || \
+	 $(GTESTER) --verbose $(TEST_PROGS)
+
+test-gdb: $(TEST_PROGS)
+	@test -z "$(TEST_PROGS)" || \
+	 for test_prog in $(TEST_PROGS); do \
+	   $(GTESTER) --verbose $$test_prog || { \
+	     gdb --ex "run --verbose" ".libs/lt-$$test_prog" ; \
+	     exit 1 ; \
+	   } \
+	 done
+
+generate-report: $(TEST_PROGS)
+	@test -z "$(TEST_PROGS)" || \
+	 $(GTESTER) $(GTESTER_ARGS) $(TEST_PROGS)
+
+
+INCLUDES = \
+	-I$(top_srcdir)		\
+	-I$(srcdir)		\
+	$(PEAS_CFLAGS)		\
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+progs_ldadd = \
+	$(PEAS_LIBS)				\
+	$(top_builddir)/libpeas/libpeas-1.0.la	\
+	./testing/libtesting.la			\
+	./introspection/libintrospection-1.0.la
+
+TEST_PROGS += \
+	engine		\
+	extension	\
+	extension-set	\
+	plugin-info
+
+engine_SOURCES = engine.c
+engine_LDADD   = $(progs_ldadd)
+
+extension_SOURCES = extension.c
+extension_LDADD   = $(progs_ldadd)
+
+extension_set_SOURCES = extension-set.c
+extension_set_LDADD   = $(progs_ldadd)
+
+plugin_info_SOURCES = plugin-info.c
+plugin_info_LDADD   = $(progs_ldadd)
diff --git a/tests/libpeas/engine.c b/tests/libpeas/engine.c
new file mode 100644
index 0000000..8784a54
--- /dev/null
+++ b/tests/libpeas/engine.c
@@ -0,0 +1,302 @@
+/*
+ * engine.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <libpeas/peas.h>
+
+#include "testing/testing.h"
+
+typedef struct _TestFixture TestFixture;
+
+struct _TestFixture {
+  PeasEngine *engine;
+};
+
+static void
+test_setup (TestFixture   *fixture,
+            gconstpointer  data)
+{
+  fixture->engine = testing_engine_new ();
+}
+
+static void
+test_teardown (TestFixture   *fixture,
+               gconstpointer  data)
+{
+  testing_engine_free (fixture->engine);
+}
+
+static void
+test_runner (TestFixture   *fixture,
+             gconstpointer  data)
+{
+  ((void (*) (PeasEngine *engine)) data) (fixture->engine);
+}
+
+static void
+test_engine_get_default (PeasEngine *engine)
+{
+  g_assert (engine != NULL);
+  g_assert (engine == peas_engine_get_default ());
+}
+
+static void
+test_engine_load_plugin (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+  g_assert (peas_plugin_info_is_loaded (info));
+}
+
+static void
+test_engine_load_plugin_with_dep (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (engine, "has-dep");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+  g_assert (peas_plugin_info_is_loaded (info));
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  g_assert (peas_plugin_info_is_loaded (info));
+}
+
+static void
+test_engine_load_plugin_with_self_dep (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (engine, "self-dep");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+  g_assert (peas_plugin_info_is_loaded (info));
+}
+
+static void
+test_engine_unload_plugin (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  test_engine_load_plugin (engine);
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  g_assert (peas_engine_unload_plugin (engine, info));
+  g_assert (!peas_plugin_info_is_loaded (info));
+}
+
+static void
+test_engine_unload_plugin_with_dep (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  test_engine_load_plugin_with_dep (engine);
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  g_assert (peas_engine_unload_plugin (engine, info));
+  g_assert (!peas_plugin_info_is_loaded (info));
+
+  info = peas_engine_get_plugin_info (engine, "has-dep");
+
+  g_assert (!peas_plugin_info_is_loaded (info));
+}
+
+static void
+test_engine_unload_plugin_with_self_dep (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  test_engine_load_plugin_with_self_dep (engine);
+
+  info = peas_engine_get_plugin_info (engine, "self-dep");
+
+  g_assert (peas_engine_unload_plugin (engine, info));
+  g_assert (!peas_plugin_info_is_loaded (info));
+}
+
+static void
+test_engine_unavailable_plugin (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (engine, "unavailable");
+
+  g_assert (!peas_engine_load_plugin (engine, info));
+  g_assert (!peas_plugin_info_is_loaded (info));
+  g_assert (!peas_plugin_info_is_available (info));
+}
+
+static void
+load_plugin_cb (PeasEngine     *engine,
+                PeasPluginInfo *info,
+                gint           *loaded)
+{
+  ++(*loaded);
+}
+
+static void
+unload_plugin_cb (PeasEngine     *engine,
+                  PeasPluginInfo *info,
+                  gint           *loaded)
+{
+  --(*loaded);
+}
+
+static void
+notify_loaded_plugins_cb (PeasEngine   *engine,
+                          GParamSpec   *pspec,
+                          gchar      ***loaded_plugins)
+{
+  if (*loaded_plugins != NULL)
+    g_strfreev (*loaded_plugins);
+
+  *loaded_plugins = peas_engine_get_loaded_plugins (engine);
+}
+
+static void
+test_engine_loaded_plugins (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  gint loaded = 0;
+  gchar **loaded_plugins = NULL;
+
+  g_signal_connect (engine,
+                    "load-plugin",
+                    G_CALLBACK (load_plugin_cb),
+                    (gpointer) &loaded);
+  g_signal_connect (engine,
+                    "unload-plugin",
+                    G_CALLBACK (unload_plugin_cb),
+                    (gpointer) &loaded);
+  g_signal_connect (engine,
+                    "notify::loaded-plugins",
+                    G_CALLBACK (notify_loaded_plugins_cb),
+                    (gpointer) &loaded_plugins);
+
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  g_assert_cmpint (loaded, ==, 1);
+  g_assert (loaded_plugins != NULL);
+  g_assert_cmpstr (loaded_plugins[0], ==, "loadable");
+  g_assert (loaded_plugins[1] == NULL);
+
+  g_assert (peas_engine_unload_plugin (engine, info));
+  g_assert (loaded_plugins == NULL);
+  g_assert_cmpint (loaded, ==, 0);
+
+
+#ifdef CANNOT_TEST
+  /* Cannot be done as unrefing the engine causes
+   * issues when another test is run
+   */
+
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  g_assert_cmpint (loaded, ==, 1);
+  g_assert (loaded_plugins != NULL);
+  g_assert_cmpstr (loaded_plugins[0], ==, "loadable");
+  g_assert (loaded_plugins[1] == NULL);
+
+  g_object_unref (engine);
+
+  g_assert_cmpint (loaded, ==, 0);
+  g_assert (loaded_plugins != NULL);
+  g_assert_cmpstr (loaded_plugins[0], ==, "loadable");
+  g_assert (loaded_plugins[1] == NULL);
+
+  if (loaded_plugins != NULL)
+    g_strfreev (loaded_plugins);
+#endif
+
+  g_signal_handlers_disconnect_by_func (engine, load_plugin_cb, &loaded);
+  g_signal_handlers_disconnect_by_func (engine, unload_plugin_cb, &loaded);
+  g_signal_handlers_disconnect_by_func (engine,
+                                        notify_loaded_plugins_cb,
+                                        &loaded_plugins);
+}
+
+#ifdef CANNOT_TEST
+static void
+test_engine_disable_loader (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  /* Cannot be run because the engine
+   * has already loaded the C plugin loader
+   */
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  peas_engine_disable_loader (engine, "C");
+
+  g_assert (!peas_engine_load_plugin (engine, info));
+  g_assert (!peas_plugin_info_is_loaded (info));
+}
+#endif
+
+int
+main (int    argc,
+      char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_type_init ();
+
+#define TEST(path, ftest) \
+  g_test_add ("/engine/" path, TestFixture, \
+              (gpointer) test_engine_##ftest, \
+              test_setup, test_runner, test_teardown)
+
+  TEST ("get-default", get_default);
+
+  TEST ("load-plugin", load_plugin);
+  TEST ("load-plugin-with-dep", load_plugin_with_dep);
+  TEST ("load-plugin-with-self-dep", load_plugin_with_self_dep);
+
+  TEST ("unload-plugin", unload_plugin);
+  TEST ("unload-plugin-with-dep", unload_plugin_with_dep);
+  TEST ("unload-plugin-with-self-dep", unload_plugin_with_self_dep);
+
+  TEST ("unavailable-plugin", unavailable_plugin);
+
+  TEST ("loaded-plugins", loaded_plugins);
+
+#ifdef CANNOT_TEST
+  TEST ("disable-loader", disable_loader);
+#endif
+
+#undef TEST
+
+  return g_test_run ();
+}
diff --git a/tests/libpeas/extension-set.c b/tests/libpeas/extension-set.c
new file mode 100644
index 0000000..77b73c0
--- /dev/null
+++ b/tests/libpeas/extension-set.c
@@ -0,0 +1,218 @@
+/*
+ * extension-set.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <libpeas/peas.h>
+
+#include "testing/testing.h"
+
+/* TODO:
+ *        - Check that extensions sets only contain extensions of their type
+ */
+
+typedef struct _TestFixture TestFixture;
+
+struct _TestFixture {
+  PeasEngine *engine;
+  PeasExtensionSet *extension_set;
+  gint active;
+};
+
+/* Have dependencies before the plugin that requires them */
+static const gchar *loadable_plugins[] = {
+  "loadable", "has-dep", "self-dep"
+};
+
+static void
+extension_added_cb (PeasExtensionSet *set,
+                    PeasPluginInfo   *info,
+                    PeasExtension    *exten,
+                    TestFixture      *fixture)
+{
+  ++fixture->active;
+}
+
+static void
+extension_removed_cb (PeasExtensionSet *set,
+                      PeasPluginInfo   *info,
+                      PeasExtension    *exten,
+                      TestFixture      *fixture)
+{
+  --fixture->active;
+}
+
+static void
+test_setup (TestFixture   *fixture,
+            gconstpointer  data)
+{
+  fixture->engine = testing_engine_new ();
+
+  fixture->extension_set = peas_extension_set_new (fixture->engine,
+                                                   PEAS_TYPE_ACTIVATABLE,
+                                                   "object", NULL,
+                                                   NULL);
+
+  g_signal_connect (fixture->extension_set,
+                    "extension-added",
+                    G_CALLBACK (extension_added_cb),
+                    fixture);
+  g_signal_connect (fixture->extension_set,
+                    "extension-removed",
+                    G_CALLBACK (extension_removed_cb),
+                    fixture);
+
+  fixture->active = 0;
+}
+
+static void
+test_teardown (TestFixture   *fixture,
+               gconstpointer  data)
+{
+  g_object_unref (fixture->extension_set);
+  g_assert_cmpint (fixture->active, ==, 0);
+
+  testing_engine_free (fixture->engine);
+}
+
+static void
+test_runner (TestFixture   *fixture,
+             gconstpointer  data)
+{
+  ((void (*) (TestFixture *fixture)) data) (fixture);
+}
+
+static void
+test_extension_set_no_extensions (TestFixture *fixture)
+{
+  /* Done in teardown */
+}
+
+static void
+test_extension_set_activate (TestFixture *fixture)
+{
+  gint i;
+  PeasPluginInfo *info;
+
+  for (i = 0; i < G_N_ELEMENTS (loadable_plugins); ++i)
+    {
+      g_assert_cmpint (fixture->active, ==, i);
+
+      info = peas_engine_get_plugin_info (fixture->engine,
+                                          loadable_plugins[i]);
+
+      g_assert (peas_engine_load_plugin (fixture->engine, info));
+    }
+
+  g_assert_cmpint (fixture->active, ==, G_N_ELEMENTS (loadable_plugins));
+}
+
+static void
+test_extension_set_deactivate (TestFixture *fixture)
+{
+  gint i;
+  PeasPluginInfo *info;
+
+  test_extension_set_activate (fixture);
+
+  /* To keep deps in order */
+  for (i = G_N_ELEMENTS (loadable_plugins); i > 0; --i)
+    {
+      g_assert_cmpint (fixture->active, ==, i);
+
+      info = peas_engine_get_plugin_info (fixture->engine,
+                                          loadable_plugins[i - 1]);
+
+      g_assert (peas_engine_unload_plugin (fixture->engine, info));
+    }
+
+  g_assert_cmpint (fixture->active, ==, 0);
+}
+
+static void
+test_extension_set_get_extension (TestFixture *fixture)
+{
+  PeasPluginInfo *info;
+  PeasExtension *extension;
+
+  info = peas_engine_get_plugin_info (fixture->engine, loadable_plugins[0]);
+
+  g_assert (peas_extension_set_get_extension (fixture->extension_set, info) == NULL);
+  g_assert (peas_engine_load_plugin (fixture->engine, info));
+
+  extension = peas_extension_set_get_extension (fixture->extension_set, info);
+
+  g_assert (PEAS_IS_ACTIVATABLE (extension));
+}
+
+static void
+test_extension_set_call_valid (TestFixture *fixture)
+{
+  test_extension_set_activate (fixture);
+
+  g_assert (peas_extension_set_call (fixture->extension_set, "activate", NULL));
+}
+
+static void
+test_extension_set_call_invalid (TestFixture *fixture)
+{
+  test_extension_set_activate (fixture);
+
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+    {
+      peas_extension_set_call (fixture->extension_set, "invalid", NULL);
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*Method 'PeasActivatable.invalid' not found*");
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_type_init ();
+
+#define TEST(path, ftest) \
+  g_test_add ("/extension-set/" path, TestFixture, \
+              (gpointer) test_extension_set_##ftest, \
+              test_setup, test_runner, test_teardown)
+
+  TEST ("no-extensions", no_extensions);
+  TEST ("activate", activate);
+  TEST ("deactivate", deactivate);
+
+  TEST ("get-extension", get_extension);
+
+  TEST ("call-valid", call_valid);
+  TEST ("call-invalid", call_invalid);
+
+#undef TEST
+
+  return g_test_run ();
+}
diff --git a/tests/libpeas/extension.c b/tests/libpeas/extension.c
new file mode 100644
index 0000000..9b8d66f
--- /dev/null
+++ b/tests/libpeas/extension.c
@@ -0,0 +1,277 @@
+/*
+ * extension.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <libpeas/peas.h>
+
+#include "testing/testing.h"
+
+#include "introspection/introspection-callable.h"
+#include "introspection/introspection-unimplemented.h"
+
+typedef struct _TestFixture TestFixture;
+
+struct _TestFixture {
+  PeasEngine *engine;
+};
+
+static void
+test_setup (TestFixture   *fixture,
+            gconstpointer  data)
+{
+  fixture->engine = testing_engine_new ();
+}
+
+static void
+test_teardown (TestFixture   *fixture,
+               gconstpointer  data)
+{
+  testing_engine_free (fixture->engine);
+}
+
+static void
+test_runner (TestFixture   *fixture,
+             gconstpointer  data)
+{
+  ((void (*) (PeasEngine *engine)) data) (fixture->engine);
+}
+
+static void
+test_extension_create_valid (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  PeasExtension *extension;
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  extension = peas_engine_create_extension (engine, info,
+                                            PEAS_TYPE_ACTIVATABLE,
+                                            "object", NULL,
+                                            NULL);
+
+  g_assert (PEAS_IS_EXTENSION (extension));
+  g_assert (PEAS_IS_ACTIVATABLE (extension));
+
+  g_object_unref (extension);
+}
+
+static void
+test_extension_create_invalid (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  PeasExtension *extension;
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  /* Not loaded */
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+    {
+      extension = peas_engine_create_extension (engine, info,
+                                                PEAS_TYPE_ACTIVATABLE,
+                                                "object", NULL,
+                                                NULL);
+      exit (0);
+    }
+  /* Resident modules cause this to fail?
+  g_test_trap_assert_failed ();*/
+
+  peas_engine_load_plugin (engine, info);
+
+  /* Invalid GType */
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+    {
+      extension = peas_engine_create_extension (engine, info,
+                                                G_TYPE_INVALID,
+                                                NULL);
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*CRITICAL*");
+
+
+  /* GObject but not a GInterface */
+  extension = peas_engine_create_extension (engine, info,
+                                            PEAS_TYPE_ENGINE,
+                                            NULL);
+  g_assert (!PEAS_IS_EXTENSION (extension));
+
+
+  /* Does not implement this GType */
+  extension = peas_engine_create_extension (engine, info,
+                                            INTROSPECTION_TYPE_UNIMPLEMENTED,
+                                            NULL);
+  g_assert (!PEAS_IS_EXTENSION (extension));
+}
+
+static void
+test_extension_call_invalid (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  PeasExtension *extension;
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  extension = peas_engine_create_extension (engine, info,
+                                            PEAS_TYPE_ACTIVATABLE,
+                                            "object", NULL,
+                                            NULL);
+
+  g_assert (PEAS_IS_ACTIVATABLE (extension));
+
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+    {
+      peas_extension_call (extension, "invalid", NULL);
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*Method 'PeasActivatable.invalid' not found*");
+
+  g_object_unref (extension);
+}
+
+static void
+test_extension_call_no_args (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  PeasExtension *extension;
+
+  info = peas_engine_get_plugin_info (engine, "loadable");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  extension = peas_engine_create_extension (engine, info,
+                                            PEAS_TYPE_ACTIVATABLE,
+                                            "object", NULL,
+                                            NULL);
+
+  g_assert (PEAS_IS_ACTIVATABLE (extension));
+
+  g_assert (peas_extension_call (extension, "activate"));
+
+  g_object_unref (extension);
+}
+
+static void
+test_extension_call_with_return (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  PeasExtension *extension;
+  const gchar *return_val = NULL;
+
+  info = peas_engine_get_plugin_info (engine, "callable");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  extension = peas_engine_create_extension (engine, info,
+                                            INTROSPECTION_TYPE_CALLABLE,
+                                            NULL);
+
+  g_assert (INTROSPECTION_IS_CALLABLE (extension));
+
+  g_assert (peas_extension_call (extension, "call_with_return", &return_val));
+  g_assert_cmpstr (return_val, ==, "Hello, World!");
+
+  g_object_unref (extension);
+}
+
+static void
+test_extension_call_single_arg (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  PeasExtension *extension;
+  gboolean called = FALSE;
+
+  info = peas_engine_get_plugin_info (engine, "callable");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  extension = peas_engine_create_extension (engine, info,
+                                            INTROSPECTION_TYPE_CALLABLE,
+                                            NULL);
+
+  g_assert (INTROSPECTION_IS_CALLABLE (extension));
+
+  g_assert (peas_extension_call (extension, "call_single_arg", &called));
+  g_assert (called);
+
+  g_object_unref (extension);
+}
+
+static void
+test_extension_call_multi_args (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  PeasExtension *extension;
+  gboolean params[3] = { FALSE, FALSE, FALSE };
+
+  info = peas_engine_get_plugin_info (engine, "callable");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  extension = peas_engine_create_extension (engine, info,
+                                            INTROSPECTION_TYPE_CALLABLE,
+                                            NULL);
+
+  g_assert (INTROSPECTION_IS_CALLABLE (extension));
+
+  g_assert (peas_extension_call (extension, "call_multi_args",
+                                 &params[0], &params[1], &params[2]));
+  g_assert (params[0] && params[1] && params[2]);
+
+  g_object_unref (extension);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_type_init ();
+
+#define TEST(path, ftest) \
+  g_test_add ("/extension/" path, TestFixture, \
+              (gpointer) test_extension_##ftest, \
+              test_setup, test_runner, test_teardown)
+
+  TEST ("create-valid", create_valid);
+  TEST ("create-invalid", create_invalid);
+
+  TEST ("call-invalid", call_invalid);
+  TEST ("call-no-args", call_no_args);
+  TEST ("call-with-return", call_with_return);
+  TEST ("call-single-arg", call_single_arg);
+  TEST ("call-multi-args", call_multi_args);
+
+#undef TEST
+
+  return g_test_run ();
+}
diff --git a/tests/libpeas/introspection/Makefile.am b/tests/libpeas/introspection/Makefile.am
new file mode 100644
index 0000000..e10e4b7
--- /dev/null
+++ b/tests/libpeas/introspection/Makefile.am
@@ -0,0 +1,47 @@
+noinst_LTLIBRARIES = libintrospection-1.0.la
+
+INTROSPECTION_INCLUDES = \
+	-I$(top_srcdir)	\
+	-I$(srcdir)	\
+	$(PEAS_CFLAGS)
+
+INCLUDES = \
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+libintrospection_1_0_la_LDFLAGS = \
+	-export-dynamic -no-undefined -export-symbols-regex "^[^_].*"
+
+libintrospection_1_0_la_LIBADD = \
+	$(PEAS_LIBS)				\
+	$(top_builddir)/libpeas/libpeas-1.0.la
+
+libintrospection_1_0_la_SOURCES = \
+	introspection-callable.c	\
+	introspection-callable.h	\
+	introspection-unimplemented.c	\
+	introspection-unimplemented.h
+
+INCLUDES += $(INTROSPECTION_INCLUDES)
+
+
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS = Introspection-1.0.gir
+INTROSPECTION_TYPELIBS = $(INTROSPECTION_GIRS:.gir=.typelib)
+INTROSPECTION_SCANNER_ARGS = \
+	--add-include-path=$(top_builddir)/libpeas	\
+	--warn-all
+INTROSPECTION_COMPILER_ARGS = --includedir=$(top_builddir)/libpeas
+
+introspection_sources = $(libintrospection_1_0_la_SOURCES)
+
+Introspection-1.0.gir: libintrospection-1.0.la
+Introspection_1_0_gir_INCLUDES = GObject-2.0 GIRepository-2.0 Peas-1.0
+Introspection_1_0_gir_CFLAGS = $(INTROSPECTION_INCLUDES)
+Introspection_1_0_gir_LIBS = libintrospection-1.0.la
+Introspection_1_0_gir_FILES = $(addprefix $(srcdir)/,$(introspection_sources))
+
+CLEANFILES = $(INTROSPECTION_GIRS) $(INTROSPECTION_TYPELIBS)
+
+all: Introspection-1.0.typelib
+
diff --git a/tests/libpeas/introspection/introspection-callable.c b/tests/libpeas/introspection/introspection-callable.c
new file mode 100644
index 0000000..356332e
--- /dev/null
+++ b/tests/libpeas/introspection/introspection-callable.c
@@ -0,0 +1,93 @@
+/*
+ * introspection-callable.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "introspection-callable.h"
+
+G_DEFINE_INTERFACE(IntrospectionCallable, introspection_callable, G_TYPE_OBJECT)
+
+void
+introspection_callable_default_init (IntrospectionCallableInterface *iface)
+{
+}
+
+/**
+ * introspection_callable_call_with_return:
+ * @callable:
+ *
+ * Returns: (transfer full):
+ */
+const gchar *
+introspection_callable_call_with_return (IntrospectionCallable *callable)
+{
+  IntrospectionCallableInterface *iface;
+
+  g_return_val_if_fail (INTROSPECTION_IS_CALLABLE (callable), NULL);
+
+  iface = INTROSPECTION_CALLABLE_GET_IFACE (callable);
+  if (iface->call_with_return != NULL)
+    return iface->call_with_return (callable);
+
+  return NULL;
+}
+
+/**
+ * introspection_callable_call_single_arg:
+ * @callable:
+ * @called: (out):
+ */
+void
+introspection_callable_call_single_arg (IntrospectionCallable *callable,
+                                        gboolean              *called)
+{
+  IntrospectionCallableInterface *iface;
+
+  g_return_if_fail (INTROSPECTION_IS_CALLABLE (callable));
+
+  iface = INTROSPECTION_CALLABLE_GET_IFACE (callable);
+  if (iface->call_single_arg != NULL)
+    iface->call_single_arg (callable, called);
+}
+
+/**
+ * introspection_callable_call_multi_args:
+ * @callable:
+ * @called_1: (out):
+ * @called_2: (out):
+ * @called_3: (out):
+ */
+void
+introspection_callable_call_multi_args (IntrospectionCallable *callable,
+                                        gboolean              *called_1,
+                                        gboolean              *called_2,
+                                        gboolean              *called_3)
+{
+  IntrospectionCallableInterface *iface;
+
+  g_return_if_fail (INTROSPECTION_IS_CALLABLE (callable));
+
+  iface = INTROSPECTION_CALLABLE_GET_IFACE (callable);
+  if (iface->call_multi_args != NULL)
+    iface->call_multi_args (callable, called_1, called_2, called_3);
+}
diff --git a/tests/libpeas/introspection/introspection-callable.h b/tests/libpeas/introspection/introspection-callable.h
new file mode 100644
index 0000000..a98091f
--- /dev/null
+++ b/tests/libpeas/introspection/introspection-callable.h
@@ -0,0 +1,70 @@
+/*
+ * introspection-callable.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __INTROSPECTION_CALLABLE_H__
+#define __INTROSPECTION_CALLABLE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define INTROSPECTION_TYPE_CALLABLE             (introspection_callable_get_type ())
+#define INTROSPECTION_CALLABLE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), INTROSPECTION_TYPE_CALLABLE, IntrospectionCallable))
+#define INTROSPECTION_CALLABLE_IFACE(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), INTROSPECTION_TYPE_CALLABLE, IntrospectionCallableInterface))
+#define INTROSPECTION_IS_CALLABLE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INTROSPECTION_TYPE_CALLABLE))
+#define INTROSPECTION_CALLABLE_GET_IFACE(obj)   (G_TYPE_INSTANCE_GET_INTERFACE ((obj), INTROSPECTION_TYPE_CALLABLE, IntrospectionCallableInterface))
+
+typedef struct _IntrospectionCallable           IntrospectionCallable; /* dummy typedef */
+typedef struct _IntrospectionCallableInterface  IntrospectionCallableInterface;
+
+struct _IntrospectionCallableInterface {
+  GTypeInterface g_iface;
+
+  /* Virtual public methods */
+  const gchar *(*call_with_return) (IntrospectionCallable *callable);
+  void         (*call_single_arg)  (IntrospectionCallable *callable,
+                                    gboolean              *called);
+  void         (*call_multi_args)  (IntrospectionCallable *callable,
+                                    gboolean              *called_1,
+                                    gboolean              *called_2,
+                                    gboolean              *called_3);
+};
+
+/*
+ * Public methods
+ */
+GType        introspection_callable_get_type        (void) G_GNUC_CONST;
+
+const gchar *introspection_callable_call_with_return (IntrospectionCallable *callable);
+
+void         introspection_callable_call_single_arg  (IntrospectionCallable *callable,
+                                                      gboolean              *called);
+void         introspection_callable_call_multi_args  (IntrospectionCallable *callable,
+                                                      gboolean              *called_1,
+                                                      gboolean              *called_2,
+                                                      gboolean              *called_3);
+
+G_END_DECLS
+
+#endif /* __INTROSPECTION_CALLABLE_H__ */
diff --git a/tests/libpeas/introspection/introspection-unimplemented.c b/tests/libpeas/introspection/introspection-unimplemented.c
new file mode 100644
index 0000000..f537203
--- /dev/null
+++ b/tests/libpeas/introspection/introspection-unimplemented.c
@@ -0,0 +1,39 @@
+/*
+ * introspection-unimplemented.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "introspection-unimplemented.h"
+
+#include <glib.h>
+
+G_DEFINE_INTERFACE(IntrospectionUnimplemented, introspection_unimplemented, G_TYPE_OBJECT)
+
+void
+introspection_unimplemented_default_init (IntrospectionUnimplementedInterface *iface)
+{
+  /* AFAIK there is no way to make this unimplemented but
+   * in the tests no one will implement it so its fine.
+   */
+}
+
diff --git a/tests/libpeas/introspection/introspection-unimplemented.h b/tests/libpeas/introspection/introspection-unimplemented.h
new file mode 100644
index 0000000..b2992e6
--- /dev/null
+++ b/tests/libpeas/introspection/introspection-unimplemented.h
@@ -0,0 +1,52 @@
+/*
+ * introspection-unimplemented.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __INTROSPECTION_UNIMPLEMENTED_H__
+#define __INTROSPECTION_UNIMPLEMENTED_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define INTROSPECTION_TYPE_UNIMPLEMENTED             (introspection_unimplemented_get_type ())
+#define INTROSPECTION_UNIMPLEMENTED(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), INTROSPECTION_TYPE_UNIMPLEMENTED, IntrospectionUnimplemented))
+#define INTROSPECTION_UNIMPLEMENTED_IFACE(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), INTROSPECTION_TYPE_UNIMPLEMENTED, IntrospectionUnimplementedInterface))
+#define INTROSPECTION_IS_UNIMPLEMENTED(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INTROSPECTION_TYPE_UNIMPLEMENTED))
+#define INTROSPECTION_UNIMPLEMENTED_GET_IFACE(obj)   (G_TYPE_INSTANCE_GET_INTERFACE ((obj), INTROSPECTION_TYPE_UNIMPLEMENTED, IntrospectionUnimplementedInterface))
+
+typedef struct _IntrospectionUnimplemented           IntrospectionUnimplemented; /* dummy typedef */
+typedef struct _IntrospectionUnimplementedInterface  IntrospectionUnimplementedInterface;
+
+struct _IntrospectionUnimplementedInterface {
+  GTypeInterface g_iface;
+};
+
+/*
+ * Public methods
+ */
+GType introspection_unimplemented_get_type (void)  G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __INTROSPECTION_UNIMPLEMENTED_H__ */
diff --git a/tests/libpeas/plugin-info.c b/tests/libpeas/plugin-info.c
new file mode 100644
index 0000000..5617e3c
--- /dev/null
+++ b/tests/libpeas/plugin-info.c
@@ -0,0 +1,191 @@
+/*
+ * plugin-info.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <libpeas/peas.h>
+
+#include "testing/testing.h"
+
+typedef struct _TestFixture TestFixture;
+
+struct _TestFixture {
+  PeasEngine *engine;
+};
+
+static void
+test_setup (TestFixture   *fixture,
+            gconstpointer  data)
+{
+  fixture->engine = testing_engine_new ();
+}
+
+static void
+test_teardown (TestFixture   *fixture,
+               gconstpointer  data)
+{
+  testing_engine_free (fixture->engine);
+}
+
+static void
+test_runner (TestFixture   *fixture,
+             gconstpointer  data)
+{
+  ((void (*) (PeasEngine *engine)) data) (fixture->engine);
+}
+
+static void
+test_plugin_info_verify_full_info (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  const gchar **authors;
+
+  info = peas_engine_get_plugin_info (engine, "full-info");
+
+  g_assert (!peas_plugin_info_is_loaded (info));
+  g_assert (peas_plugin_info_is_available (info));
+  g_assert (peas_plugin_info_is_builtin (info));
+
+  g_assert_cmpstr (peas_plugin_info_get_module_name (info), ==, "full-info");
+  g_assert (g_str_has_suffix (peas_plugin_info_get_module_dir (info), "/tests/plugins"));
+  g_assert (g_str_has_suffix (peas_plugin_info_get_data_dir (info), "/tests/plugins/full-info"));
+
+  g_assert_cmpstr (peas_plugin_info_get_dependencies (info)[0], ==, "something");
+  g_assert_cmpstr (peas_plugin_info_get_dependencies (info)[1], ==, "something-else");
+  g_assert_cmpstr (peas_plugin_info_get_dependencies (info)[2], ==, NULL);
+
+  g_assert_cmpstr (peas_plugin_info_get_name (info), ==, "Full Info");
+  g_assert_cmpstr (peas_plugin_info_get_description (info), ==, "Has full info.");
+  g_assert_cmpstr (peas_plugin_info_get_icon_name (info), ==, "full-info-icon");
+  g_assert_cmpstr (peas_plugin_info_get_website (info), ==, "http://live.gnome.org/Libpeas";);
+  g_assert_cmpstr (peas_plugin_info_get_copyright (info), ==, "Copyright © 2010 Garrett Regier");
+  g_assert_cmpstr (peas_plugin_info_get_version (info), ==, "1.0");
+  g_assert_cmpstr (peas_plugin_info_get_help_uri (info), ==, "http://git.gnome.org/browse/libpeas";);
+  g_assert_cmpint (peas_plugin_info_get_iage (info), ==, 2);
+
+  authors = peas_plugin_info_get_authors (info);
+  g_assert (authors != NULL && authors[1] == NULL);
+  g_assert_cmpstr (authors[0], ==, "Garrett Regier");
+}
+
+static void
+test_plugin_info_verify_min_info (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (engine, "min-info");
+
+  g_assert (!peas_plugin_info_is_loaded (info));
+  g_assert (peas_plugin_info_is_available (info));
+  g_assert (!peas_plugin_info_is_builtin (info));
+
+  g_assert_cmpstr (peas_plugin_info_get_module_name (info), ==, "min-info");
+  g_assert (g_str_has_suffix (peas_plugin_info_get_module_dir (info), "/tests/plugins"));
+  g_assert (g_str_has_suffix (peas_plugin_info_get_data_dir (info), "/tests/plugins/min-info"));
+
+  g_assert_cmpstr (peas_plugin_info_get_dependencies (info)[0], ==, NULL);
+
+  g_assert_cmpstr (peas_plugin_info_get_name (info), ==, "Min Info");
+  g_assert_cmpstr (peas_plugin_info_get_description (info), ==, NULL);
+  g_assert_cmpstr (peas_plugin_info_get_icon_name (info), ==, "libpeas-plugin");
+  g_assert_cmpstr (peas_plugin_info_get_website (info), ==, NULL);
+  g_assert_cmpstr (peas_plugin_info_get_copyright (info), ==, NULL);
+  g_assert_cmpstr (peas_plugin_info_get_version (info), ==, NULL);
+  g_assert_cmpstr (peas_plugin_info_get_help_uri (info), ==, NULL);
+  g_assert_cmpint (peas_plugin_info_get_iage (info), ==, 2);
+
+  g_assert (peas_plugin_info_get_authors (info) == NULL);
+}
+
+static void
+test_plugin_info_has_dep (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  info = peas_engine_get_plugin_info (engine, "full-info");
+
+  g_assert (peas_plugin_info_has_dependency (info, "something"));
+  g_assert (peas_plugin_info_has_dependency (info, "something-else"));
+  g_assert (!peas_plugin_info_has_dependency (info, "does-not-exist"));
+
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+    {
+      peas_plugin_info_has_dependency (info, NULL);
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*CRITICAL*");
+
+
+  info = peas_engine_get_plugin_info (engine, "min-info");
+
+  g_assert (!peas_plugin_info_has_dependency (info, "does-not-exist"));
+}
+
+static void
+test_plugin_info_missing_iage (PeasEngine *engine)
+{
+  g_assert (peas_engine_get_plugin_info (engine, "invalid-info-iage") == NULL);
+}
+
+static void
+test_plugin_info_missing_module (PeasEngine *engine)
+{
+  g_assert (peas_engine_get_plugin_info (engine, "invalid-info-module") == NULL);
+}
+
+static void
+test_plugin_info_missing_name (PeasEngine *engine)
+{
+  g_assert (peas_engine_get_plugin_info (engine, "invalid-info-name") == NULL);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_type_init ();
+
+#define TEST(path, ftest) \
+  g_test_add ("/plugin-info/" path, TestFixture, \
+              (gpointer) test_plugin_info_##ftest, \
+              test_setup, test_runner, test_teardown)
+
+  TEST ("verify-full-info", verify_full_info);
+  TEST ("verify-min-info", verify_min_info);
+
+  TEST ("has-dep", has_dep);
+
+  TEST ("missing-iage", missing_iage);
+  TEST ("missing-module", missing_module);
+  TEST ("missing-name", missing_name);
+
+#undef TEST
+
+  return g_test_run ();
+}
diff --git a/tests/libpeas/plugins/Makefile.am b/tests/libpeas/plugins/Makefile.am
new file mode 100644
index 0000000..a0435ac
--- /dev/null
+++ b/tests/libpeas/plugins/Makefile.am
@@ -0,0 +1,8 @@
+SUBDIRS = callable
+
+noinst_DATA = \
+	info-missing-iage.plugin	\
+	info-missing-module.plugin	\
+	info-missing-name.plugin
+
+EXTRA_DIST = $(noinst_DATA)
diff --git a/tests/libpeas/plugins/callable-python/Makefile.am b/tests/libpeas/plugins/callable-python/Makefile.am
new file mode 100644
index 0000000..f17f6a5
--- /dev/null
+++ b/tests/libpeas/plugins/callable-python/Makefile.am
@@ -0,0 +1,7 @@
+plugindir = "$(abs_top_srcdir)/.dummy-install/plugins"
+
+plugin_PYTHON = callable-python-plugin.py
+
+plugin_DATA = callable-python.plugin
+
+EXTRA_DIST = $(plugin_DATA)
diff --git a/tests/libpeas/plugins/callable-python/callable-python-plugin.py b/tests/libpeas/plugins/callable-python/callable-python-plugin.py
new file mode 100644
index 0000000..0423793
--- /dev/null
+++ b/tests/libpeas/plugins/callable-python/callable-python-plugin.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# ex:set ts=4 et sw=4 ai:
+
+import gobject
+from gi.repository import Introspection
+
+class CallablePythonPlugin(gobject.GObject, Introspection.Callable):
+    __gtype__ = "CallablePythonPlugin"
+
+    def do_call_with_return(self):
+        return "Hello, World!";
+
+    def do_call_single_arg(self, called):
+        called = True
+
+    def do_call_multi_args(self, called_1, called_2, called_3):
+        called_1 = True
+        called_2 = True
+        called_3 = True
diff --git a/tests/libpeas/plugins/callable-python/callable-python.plugin b/tests/libpeas/plugins/callable-python/callable-python.plugin
new file mode 100644
index 0000000..42269a8
--- /dev/null
+++ b/tests/libpeas/plugins/callable-python/callable-python.plugin
@@ -0,0 +1,8 @@
+[Plugin]
+Module=callable
+IAge=2
+Name=Callable
+Description=This plugin can be loaded and is callable.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
diff --git a/tests/libpeas/plugins/callable/Makefile.am b/tests/libpeas/plugins/callable/Makefile.am
new file mode 100644
index 0000000..4a7be13
--- /dev/null
+++ b/tests/libpeas/plugins/callable/Makefile.am
@@ -0,0 +1,19 @@
+INCLUDES = \
+	-I$(top_srcdir)		\
+	-I$(srcdir)/../../introspection	\
+	$(PEAS_CFLAGS)		\
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+noinst_LTLIBRARIES = libcallable.la
+
+libcallable_la_SOURCES = \
+	callable-plugin.c	\
+	callable-plugin.h
+
+libcallable_la_LDFLAGS = $(TEST_PLUGIN_LIBTOOL_FLAGS)
+libcallable_la_LIBADD  = $(PEAS_LIBS)
+
+noinst_DATA = callable.plugin
+
+EXTRA_DIST = $(noinst_DATA)
diff --git a/tests/libpeas/plugins/callable/callable-plugin.c b/tests/libpeas/plugins/callable/callable-plugin.c
new file mode 100644
index 0000000..3167295
--- /dev/null
+++ b/tests/libpeas/plugins/callable/callable-plugin.c
@@ -0,0 +1,100 @@
+/*
+ * callable-plugin.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <libpeas/peas.h>
+
+#include "introspection-callable.h"
+
+#include "callable-plugin.h"
+
+static void introspection_callable_iface_init (IntrospectionCallableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingCallablePlugin,
+                                testing_callable_plugin,
+                                PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (INTROSPECTION_TYPE_CALLABLE,
+                                                               introspection_callable_iface_init))
+
+static void
+testing_callable_plugin_init (TestingCallablePlugin *plugin)
+{
+}
+
+static const gchar *
+testing_callable_plugin_call_with_return (IntrospectionCallable *callable)
+{
+  return "Hello, World!";
+}
+
+static void
+testing_callable_plugin_call_single_arg (IntrospectionCallable *callable,
+                                         gboolean              *called)
+{
+  *called = TRUE;
+}
+
+static void
+testing_callable_plugin_call_multi_args (IntrospectionCallable *callable,
+                                         gboolean              *called_1,
+                                         gboolean              *called_2,
+                                         gboolean              *called_3)
+{
+  *called_1 = TRUE;
+  *called_2 = TRUE;
+  *called_3 = TRUE;
+}
+
+static void
+testing_callable_plugin_class_init (TestingCallablePluginClass *klass)
+{
+}
+
+static void
+introspection_callable_iface_init (IntrospectionCallableInterface *iface)
+{
+  iface->call_with_return = testing_callable_plugin_call_with_return;
+  iface->call_single_arg = testing_callable_plugin_call_single_arg;
+  iface->call_multi_args = testing_callable_plugin_call_multi_args;
+}
+
+static void
+testing_callable_plugin_class_finalize (TestingCallablePluginClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+  testing_callable_plugin_register_type (G_TYPE_MODULE (module));
+
+  peas_object_module_register_extension_type (module,
+                                              INTROSPECTION_TYPE_CALLABLE,
+                                              TESTING_TYPE_CALLABLE_PLUGIN);
+}
diff --git a/tests/libpeas/plugins/callable/callable-plugin.h b/tests/libpeas/plugins/callable/callable-plugin.h
new file mode 100644
index 0000000..911a7a4
--- /dev/null
+++ b/tests/libpeas/plugins/callable/callable-plugin.h
@@ -0,0 +1,52 @@
+/*
+ * callable-plugin.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_CALLABLE_PLUGIN_H__
+#define __TESTING_CALLABLE_PLUGIN_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_CALLABLE_PLUGIN         (testing_callable_plugin_get_type ())
+#define TESTING_CALLABLE_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_CALLABLE_PLUGIN, TestingCallablePlugin))
+#define TESTING_CALLABLE_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_CALLABLE_PLUGIN, TestingCallablePlugin))
+#define TESTING_IS_CALLABLE_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_CALLABLE_PLUGIN))
+#define TESTING_IS_CALLABLE_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_CALLABLE_PLUGIN))
+#define TESTING_CALLABLE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_CALLABLE_PLUGIN, TestingCallablePluginClass))
+
+typedef struct _TestingCallablePlugin         TestingCallablePlugin;
+typedef struct _TestingCallablePluginClass    TestingCallablePluginClass;
+
+struct _TestingCallablePlugin {
+  PeasExtensionBase parent_instance;
+};
+
+struct _TestingCallablePluginClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+GType                 testing_callable_plugin_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void  peas_register_types              (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_CALLABLE_PLUGIN_H__ */
diff --git a/tests/libpeas/plugins/callable/callable.plugin b/tests/libpeas/plugins/callable/callable.plugin
new file mode 100644
index 0000000..42269a8
--- /dev/null
+++ b/tests/libpeas/plugins/callable/callable.plugin
@@ -0,0 +1,8 @@
+[Plugin]
+Module=callable
+IAge=2
+Name=Callable
+Description=This plugin can be loaded and is callable.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
diff --git a/tests/libpeas/plugins/info-missing-iage.plugin b/tests/libpeas/plugins/info-missing-iage.plugin
new file mode 100644
index 0000000..77cae33
--- /dev/null
+++ b/tests/libpeas/plugins/info-missing-iage.plugin
@@ -0,0 +1,3 @@
+[Plugin]
+Module=info-missing-iage
+Name=Info Missing IAge
diff --git a/tests/libpeas/plugins/info-missing-module.plugin b/tests/libpeas/plugins/info-missing-module.plugin
new file mode 100644
index 0000000..9d38a31
--- /dev/null
+++ b/tests/libpeas/plugins/info-missing-module.plugin
@@ -0,0 +1,3 @@
+[Plugin]
+IAge=2
+Name=Info Missing Module
diff --git a/tests/libpeas/plugins/info-missing-name.plugin b/tests/libpeas/plugins/info-missing-name.plugin
new file mode 100644
index 0000000..f99c637
--- /dev/null
+++ b/tests/libpeas/plugins/info-missing-name.plugin
@@ -0,0 +1,3 @@
+[Plugin]
+Module=info-missing-name
+IAge=2
diff --git a/tests/libpeas/testing/Makefile.am b/tests/libpeas/testing/Makefile.am
new file mode 100644
index 0000000..ebd6457
--- /dev/null
+++ b/tests/libpeas/testing/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = \
+	-I$(top_srcdir)				\
+	-I$(srcdir)				\
+	$(PEAS_CFLAGS)				\
+	$(WARN_CFLAGS)				\
+	$(DISABLE_DEPRECATED)			\
+	-DBUILDDIR="\"$(abs_top_builddir)\""
+
+noinst_LTLIBRARIES = libtesting.la
+
+libtesting_la_LDFLAGS = \
+	-export-dynamic -no-undefined -export-symbols-regex "^[^_].*"
+
+libtesting_la_LIBADD = \
+	$(PEAS_LIBS)				\
+	$(top_builddir)/libpeas/libpeas-1.0.la
+
+libtesting_la_SOURCES = testing.c testing.h
diff --git a/tests/libpeas/testing/testing.c b/tests/libpeas/testing/testing.c
new file mode 100644
index 0000000..af7cdf4
--- /dev/null
+++ b/tests/libpeas/testing/testing.c
@@ -0,0 +1,146 @@
+/*
+ * testing.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <girepository.h>
+
+#include "libpeas/peas-plugin-info-priv.h"
+
+#include "testing.h"
+
+static GLogFunc default_log_func;
+
+/* These are warning that just have to happen for testing
+ * purposes and as such we don't want to abort on them.
+ *
+ * Would be nice if we could assert that they were...
+ */
+static const gchar *allowed_patterns[] = {
+  "*Plugin not found: does-not-exist*",
+  "*libcloader.so*cannot open shared object file: No such file or directory*",
+  "*Could not find 'IAge' in *info-missing-iage.plugin*",
+  "*Could not find 'Module' in *info-missing-module.plugin*",
+  "*Could not find 'Name' in *info-missing-name.plugin*",
+  "*Error loading *info-missing-iage.plugin*",
+  "*Error loading *info-missing-module.plugin*",
+  "*Error loading *info-missing-name.plugin*"
+};
+
+static void
+log_handler (const gchar    *log_domain,
+             GLogLevelFlags  log_level,
+             const gchar    *message,
+             gpointer        user_data)
+{
+  gint i;
+
+  if ((log_level & G_LOG_LEVEL_DEBUG) != 0 ||
+      (log_level & G_LOG_LEVEL_INFO) != 0 ||
+      (log_level & G_LOG_LEVEL_MESSAGE) != 0)
+    {
+      default_log_func (log_domain, log_level, message, user_data);
+      return;
+    }
+
+  if ((log_level & G_LOG_LEVEL_CRITICAL) != 0 ||
+      (log_level & G_LOG_LEVEL_ERROR) != 0)
+    {
+      goto out;
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (allowed_patterns); ++i)
+    {
+      if (g_pattern_match_simple (allowed_patterns[i], message))
+        return;
+    }
+
+out:
+
+  default_log_func (log_domain, log_level, message, user_data);
+
+  /* Make sure we abort for warnings */
+  abort ();
+}
+
+PeasEngine *
+testing_engine_new (void)
+{
+  PeasEngine *engine;
+  GError *error = NULL;
+  static gboolean initialized = FALSE;
+
+  if (initialized)
+    return peas_engine_get_default ();
+
+  /* Don't always abort on warnings */
+  g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
+
+  default_log_func = g_log_set_default_handler (log_handler, NULL);
+
+  g_irepository_prepend_search_path (BUILDDIR "/libpeas");
+
+  g_setenv ("PEAS_PLUGIN_LOADERS_DIR", BUILDDIR "/loaders", TRUE);
+
+  g_irepository_require (g_irepository_get_default (), "Peas", "1.0", 0, &error);
+  g_assert_no_error (error);
+
+  g_irepository_require_private (g_irepository_get_default (),
+                                 BUILDDIR "/tests/libpeas/introspection",
+                                 "Introspection", "1.0", 0, &error);
+  g_assert_no_error (error);
+
+  /* Must be after requiring typelibs */
+  engine = peas_engine_get_default ();
+
+  peas_engine_add_search_path (engine, BUILDDIR "/tests/plugins", NULL);
+  peas_engine_add_search_path (engine, BUILDDIR "/tests/libpeas/plugins", NULL);
+  peas_engine_rescan_plugins (engine);
+
+  initialized = TRUE;
+
+  return engine;
+}
+
+void
+testing_engine_free (PeasEngine *engine)
+{
+  const GList *plugins;
+
+  /* This causes errors during the next test:
+  g_object_unref (engine);*/
+
+  /* Otherwise the tests may cause each other to fail
+   * because they expected a plugin to be available
+   * but it failed loading making it unavailable
+   */
+  plugins = peas_engine_get_plugin_list (engine);
+  for (; plugins != NULL; plugins = plugins->next)
+    ((PeasPluginInfo *) plugins->data)->available = TRUE;
+
+  peas_engine_set_loaded_plugins (engine, NULL);
+  g_assert (peas_engine_get_loaded_plugins (engine) == NULL);
+}
diff --git a/tests/libpeas/testing/testing.h b/tests/libpeas/testing/testing.h
new file mode 100644
index 0000000..31c486c
--- /dev/null
+++ b/tests/libpeas/testing/testing.h
@@ -0,0 +1,34 @@
+/*
+ * testing.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_H__
+#define __TESTING_H__
+
+#include <libpeas/peas-engine.h>
+
+G_BEGIN_DECLS
+
+PeasEngine *testing_engine_new  (void);
+void        testing_engine_free (PeasEngine *engine);
+
+G_END_DECLS
+
+#endif /* __TESTING_H__ */
diff --git a/tests/plugins/Makefile.am b/tests/plugins/Makefile.am
new file mode 100644
index 0000000..7aa557e
--- /dev/null
+++ b/tests/plugins/Makefile.am
@@ -0,0 +1,12 @@
+SUBDIRS = \
+	builtin			\
+	has-dep			\
+	loadable		\
+	self-dep
+
+noinst_DATA = \
+	full-info.plugin		\
+	min-info.plugin			\
+	unavailable.plugin
+
+EXTRA_DIST = $(noinst_DATA)
diff --git a/tests/plugins/builtin/Makefile.am b/tests/plugins/builtin/Makefile.am
new file mode 100644
index 0000000..ba295e4
--- /dev/null
+++ b/tests/plugins/builtin/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = \
+	-I$(top_srcdir)		\
+	$(PEAS_CFLAGS)		\
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+noinst_LTLIBRARIES = libbuiltin.la
+
+libbuiltin_la_SOURCES = \
+	builtin-plugin.c	\
+	builtin-plugin.h
+
+libbuiltin_la_LDFLAGS = $(TEST_PLUGIN_LIBTOOL_FLAGS)
+libbuiltin_la_LIBADD  = $(PEAS_LIBS)
+
+noinst_DATA = builtin.plugin
+
+EXTRA_DIST = $(noinst_DATA)
diff --git a/tests/plugins/builtin/builtin-plugin.c b/tests/plugins/builtin/builtin-plugin.c
new file mode 100644
index 0000000..dd0d331
--- /dev/null
+++ b/tests/plugins/builtin/builtin-plugin.c
@@ -0,0 +1,143 @@
+/*
+ * builtin-plugin.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <libpeas/peas.h>
+
+#include "builtin-plugin.h"
+
+struct _TestingBuiltinPluginPrivate {
+  GObject *object;
+};
+
+static void peas_activatable_iface_init (PeasActivatableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingBuiltinPlugin,
+                                testing_builtin_plugin,
+                                PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_TYPE_ACTIVATABLE,
+                                                               peas_activatable_iface_init))
+
+enum {
+  PROP_0,
+  PROP_OBJECT
+};
+
+static void
+testing_builtin_plugin_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  TestingBuiltinPlugin *plugin = TESTING_BUILTIN_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      plugin->priv->object = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_builtin_plugin_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  TestingBuiltinPlugin *plugin = TESTING_BUILTIN_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      g_value_set_object (value, plugin->priv->object);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_builtin_plugin_init (TestingBuiltinPlugin *plugin)
+{
+  plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin,
+                                              TESTING_TYPE_BUILTIN_PLUGIN,
+                                              TestingBuiltinPluginPrivate);
+}
+
+static void
+testing_builtin_plugin_activate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_builtin_plugin_deactivate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_builtin_plugin_class_init (TestingBuiltinPluginClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = testing_builtin_plugin_set_property;
+  object_class->get_property = testing_builtin_plugin_get_property;
+
+  g_object_class_override_property (object_class, PROP_OBJECT, "object");
+
+  g_type_class_add_private (klass, sizeof (TestingBuiltinPluginPrivate));
+}
+
+static void
+peas_activatable_iface_init (PeasActivatableInterface *iface)
+{
+  iface->activate = testing_builtin_plugin_activate;
+  iface->deactivate = testing_builtin_plugin_deactivate;
+}
+
+static void
+testing_builtin_plugin_class_finalize (TestingBuiltinPluginClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+  testing_builtin_plugin_register_type (G_TYPE_MODULE (module));
+
+  peas_object_module_register_extension_type (module,
+                                              PEAS_TYPE_ACTIVATABLE,
+                                              TESTING_TYPE_BUILTIN_PLUGIN);
+}
diff --git a/tests/plugins/builtin/builtin-plugin.h b/tests/plugins/builtin/builtin-plugin.h
new file mode 100644
index 0000000..5eefda5
--- /dev/null
+++ b/tests/plugins/builtin/builtin-plugin.h
@@ -0,0 +1,55 @@
+/*
+ * builtin-plugin.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_BUILTIN_PLUGIN_H__
+#define __TESTING_BUILTIN_PLUGIN_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_BUILTIN_PLUGIN         (testing_builtin_plugin_get_type ())
+#define TESTING_BUILTIN_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_BUILTIN_PLUGIN, TestingBuiltinPlugin))
+#define TESTING_BUILTIN_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_BUILTIN_PLUGIN, TestingBuiltinPlugin))
+#define TESTING_IS_BUILTIN_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_BUILTIN_PLUGIN))
+#define TESTING_IS_BUILTIN_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_BUILTIN_PLUGIN))
+#define TESTING_BUILTIN_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_BUILTIN_PLUGIN, TestingBuiltinPluginClass))
+
+typedef struct _TestingBuiltinPlugin         TestingBuiltinPlugin;
+typedef struct _TestingBuiltinPluginClass    TestingBuiltinPluginClass;
+typedef struct _TestingBuiltinPluginPrivate  TestingBuiltinPluginPrivate;
+
+struct _TestingBuiltinPlugin {
+  PeasExtensionBase parent_instance;
+
+  TestingBuiltinPluginPrivate *priv;
+};
+
+struct _TestingBuiltinPluginClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+GType                 testing_builtin_plugin_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void  peas_register_types             (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_BUILTIN_PLUGIN_H__ */
diff --git a/tests/plugins/builtin/builtin.plugin b/tests/plugins/builtin/builtin.plugin
new file mode 100644
index 0000000..7585f25
--- /dev/null
+++ b/tests/plugins/builtin/builtin.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=builtin
+IAge=2
+Name=Builtin
+Description=A plugin that can be loaded and is builtin.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
+Builtin=true
diff --git a/tests/plugins/full-info.plugin b/tests/plugins/full-info.plugin
new file mode 100644
index 0000000..21ee9c9
--- /dev/null
+++ b/tests/plugins/full-info.plugin
@@ -0,0 +1,13 @@
+[Plugin]
+Module=full-info
+Depends=something;something-else
+IAge=2
+Builtin=true
+Name=Full Info
+Description=Has full info.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
+Icon=full-info-icon
+Version=1.0
+Help=http://git.gnome.org/browse/libpeas
diff --git a/tests/plugins/has-dep/Makefile.am b/tests/plugins/has-dep/Makefile.am
new file mode 100644
index 0000000..eb66377
--- /dev/null
+++ b/tests/plugins/has-dep/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = \
+	-I$(top_srcdir)		\
+	$(PEAS_CFLAGS)		\
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+noinst_LTLIBRARIES = libhas-dep.la
+
+libhas_dep_la_SOURCES = \
+	has-dep-plugin.c	\
+	has-dep-plugin.h
+
+libhas_dep_la_LDFLAGS = $(TEST_PLUGIN_LIBTOOL_FLAGS)
+libhas_dep_la_LIBADD  = $(PEAS_LIBS)
+
+noinst_DATA = has-dep.plugin
+
+EXTRA_DIST = $(noinst_DATA)
diff --git a/tests/plugins/has-dep/has-dep-plugin.c b/tests/plugins/has-dep/has-dep-plugin.c
new file mode 100644
index 0000000..5e3c9b7
--- /dev/null
+++ b/tests/plugins/has-dep/has-dep-plugin.c
@@ -0,0 +1,143 @@
+/*
+ * has-dep-plugin.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <libpeas/peas.h>
+
+#include "has-dep-plugin.h"
+
+struct _TestingHasDepPluginPrivate {
+  GObject *object;
+};
+
+static void peas_activatable_iface_init (PeasActivatableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingHasDepPlugin,
+                                testing_has_dep_plugin,
+                                PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_TYPE_ACTIVATABLE,
+                                                               peas_activatable_iface_init))
+
+enum {
+  PROP_0,
+  PROP_OBJECT
+};
+
+static void
+testing_has_dep_plugin_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  TestingHasDepPlugin *plugin = TESTING_HAS_DEP_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      plugin->priv->object = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_has_dep_plugin_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  TestingHasDepPlugin *plugin = TESTING_HAS_DEP_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      g_value_set_object (value, plugin->priv->object);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_has_dep_plugin_init (TestingHasDepPlugin *plugin)
+{
+  plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin,
+                                              TESTING_TYPE_HAS_DEP_PLUGIN,
+                                              TestingHasDepPluginPrivate);
+}
+
+static void
+testing_has_dep_plugin_activate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_has_dep_plugin_deactivate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_has_dep_plugin_class_init (TestingHasDepPluginClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = testing_has_dep_plugin_set_property;
+  object_class->get_property = testing_has_dep_plugin_get_property;
+
+  g_object_class_override_property (object_class, PROP_OBJECT, "object");
+
+  g_type_class_add_private (klass, sizeof (TestingHasDepPluginPrivate));
+}
+
+static void
+peas_activatable_iface_init (PeasActivatableInterface *iface)
+{
+  iface->activate = testing_has_dep_plugin_activate;
+  iface->deactivate = testing_has_dep_plugin_deactivate;
+}
+
+static void
+testing_has_dep_plugin_class_finalize (TestingHasDepPluginClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+  testing_has_dep_plugin_register_type (G_TYPE_MODULE (module));
+
+  peas_object_module_register_extension_type (module,
+                                              PEAS_TYPE_ACTIVATABLE,
+                                              TESTING_TYPE_HAS_DEP_PLUGIN);
+}
diff --git a/tests/plugins/has-dep/has-dep-plugin.h b/tests/plugins/has-dep/has-dep-plugin.h
new file mode 100644
index 0000000..14fc023
--- /dev/null
+++ b/tests/plugins/has-dep/has-dep-plugin.h
@@ -0,0 +1,55 @@
+/*
+ * has-dep-plugin.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_HAS_DEP_PLUGIN_H__
+#define __TESTING_HAS_DEP_PLUGIN_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_HAS_DEP_PLUGIN         (testing_has_dep_plugin_get_type ())
+#define TESTING_HAS_DEP_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_HAS_DEP_PLUGIN, TestingHasDepPlugin))
+#define TESTING_HAS_DEP_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_HAS_DEP_PLUGIN, TestingHasDepPlugin))
+#define TESTING_IS_HAS_DEP_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_HAS_DEP_PLUGIN))
+#define TESTING_IS_HAS_DEP_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_HAS_DEP_PLUGIN))
+#define TESTING_HAS_DEP_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_HAS_DEP_PLUGIN, TestingHasDepPluginClass))
+
+typedef struct _TestingHasDepPlugin         TestingHasDepPlugin;
+typedef struct _TestingHasDepPluginClass    TestingHasDepPluginClass;
+typedef struct _TestingHasDepPluginPrivate  TestingHasDepPluginPrivate;
+
+struct _TestingHasDepPlugin {
+  PeasExtensionBase parent_instance;
+
+  TestingHasDepPluginPrivate *priv;
+};
+
+struct _TestingHasDepPluginClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+GType                 testing_has_dep_plugin_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void  peas_register_types             (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_HAS_DEP_PLUGIN_H__ */
diff --git a/tests/plugins/has-dep/has-dep.plugin b/tests/plugins/has-dep/has-dep.plugin
new file mode 100644
index 0000000..0c6a4da
--- /dev/null
+++ b/tests/plugins/has-dep/has-dep.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=has-dep
+Depends=loadable
+IAge=2
+Name=Has Dep
+Description=This plugin can be loaded and has a dep.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
diff --git a/tests/plugins/loadable/Makefile.am b/tests/plugins/loadable/Makefile.am
new file mode 100644
index 0000000..1d9f5af
--- /dev/null
+++ b/tests/plugins/loadable/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = \
+	-I$(top_srcdir)		\
+	$(PEAS_CFLAGS)		\
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+noinst_LTLIBRARIES = libloadable.la
+
+libloadable_la_SOURCES = \
+	loadable-plugin.c	\
+	loadable-plugin.h
+
+libloadable_la_LDFLAGS = $(TEST_PLUGIN_LIBTOOL_FLAGS)
+libloadable_la_LIBADD  = $(PEAS_LIBS)
+
+noinst_DATA = loadable.plugin
+
+EXTRA_DIST = $(noinst_DATA)
diff --git a/tests/plugins/loadable/loadable-plugin.c b/tests/plugins/loadable/loadable-plugin.c
new file mode 100644
index 0000000..bca7f2f
--- /dev/null
+++ b/tests/plugins/loadable/loadable-plugin.c
@@ -0,0 +1,143 @@
+/*
+ * loadable-plugin.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <libpeas/peas.h>
+
+#include "loadable-plugin.h"
+
+struct _TestingLoadablePluginPrivate {
+  GObject *object;
+};
+
+static void peas_activatable_iface_init (PeasActivatableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingLoadablePlugin,
+                                testing_loadable_plugin,
+                                PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_TYPE_ACTIVATABLE,
+                                                               peas_activatable_iface_init))
+
+enum {
+  PROP_0,
+  PROP_OBJECT
+};
+
+static void
+testing_loadable_plugin_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  TestingLoadablePlugin *plugin = TESTING_LOADABLE_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      plugin->priv->object = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_loadable_plugin_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  TestingLoadablePlugin *plugin = TESTING_LOADABLE_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      g_value_set_object (value, plugin->priv->object);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_loadable_plugin_init (TestingLoadablePlugin *plugin)
+{
+  plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin,
+                                              TESTING_TYPE_LOADABLE_PLUGIN,
+                                              TestingLoadablePluginPrivate);
+}
+
+static void
+testing_loadable_plugin_activate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_loadable_plugin_deactivate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_loadable_plugin_class_init (TestingLoadablePluginClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = testing_loadable_plugin_set_property;
+  object_class->get_property = testing_loadable_plugin_get_property;
+
+  g_object_class_override_property (object_class, PROP_OBJECT, "object");
+
+  g_type_class_add_private (klass, sizeof (TestingLoadablePluginPrivate));
+}
+
+static void
+peas_activatable_iface_init (PeasActivatableInterface *iface)
+{
+  iface->activate = testing_loadable_plugin_activate;
+  iface->deactivate = testing_loadable_plugin_deactivate;
+}
+
+static void
+testing_loadable_plugin_class_finalize (TestingLoadablePluginClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+  testing_loadable_plugin_register_type (G_TYPE_MODULE (module));
+
+  peas_object_module_register_extension_type (module,
+                                              PEAS_TYPE_ACTIVATABLE,
+                                              TESTING_TYPE_LOADABLE_PLUGIN);
+}
diff --git a/tests/plugins/loadable/loadable-plugin.h b/tests/plugins/loadable/loadable-plugin.h
new file mode 100644
index 0000000..273bf91
--- /dev/null
+++ b/tests/plugins/loadable/loadable-plugin.h
@@ -0,0 +1,55 @@
+/*
+ * loadable-plugin.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_LOADABLE_PLUGIN_H__
+#define __TESTING_LOADABLE_PLUGIN_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_LOADABLE_PLUGIN         (testing_loadable_plugin_get_type ())
+#define TESTING_LOADABLE_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_LOADABLE_PLUGIN, TestingLoadablePlugin))
+#define TESTING_LOADABLE_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_LOADABLE_PLUGIN, TestingLoadablePlugin))
+#define TESTING_IS_LOADABLE_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_LOADABLE_PLUGIN))
+#define TESTING_IS_LOADABLE_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_LOADABLE_PLUGIN))
+#define TESTING_LOADABLE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_LOADABLE_PLUGIN, TestingLoadablePluginClass))
+
+typedef struct _TestingLoadablePlugin         TestingLoadablePlugin;
+typedef struct _TestingLoadablePluginClass    TestingLoadablePluginClass;
+typedef struct _TestingLoadablePluginPrivate  TestingLoadablePluginPrivate;
+
+struct _TestingLoadablePlugin {
+  PeasExtensionBase parent_instance;
+
+  TestingLoadablePluginPrivate *priv;
+};
+
+struct _TestingLoadablePluginClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+GType                 testing_loadable_plugin_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void  peas_register_types              (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_LOADABLE_PLUGIN_H__ */
diff --git a/tests/plugins/loadable/loadable.plugin b/tests/plugins/loadable/loadable.plugin
new file mode 100644
index 0000000..b7e40b1
--- /dev/null
+++ b/tests/plugins/loadable/loadable.plugin
@@ -0,0 +1,8 @@
+[Plugin]
+Module=loadable
+IAge=2
+Name=Loadable
+Description=A plugin that can be loaded.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
diff --git a/tests/plugins/min-info.plugin b/tests/plugins/min-info.plugin
new file mode 100644
index 0000000..daff8ad
--- /dev/null
+++ b/tests/plugins/min-info.plugin
@@ -0,0 +1,4 @@
+[Plugin]
+Module=min-info
+IAge=2
+Name=Min Info
diff --git a/tests/plugins/self-dep/Makefile.am b/tests/plugins/self-dep/Makefile.am
new file mode 100644
index 0000000..24e1240
--- /dev/null
+++ b/tests/plugins/self-dep/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = \
+	-I$(top_srcdir)		\
+	$(PEAS_CFLAGS)		\
+	$(WARN_CFLAGS)		\
+	$(DISABLE_DEPRECATED)
+
+noinst_LTLIBRARIES = libself-dep.la
+
+libself_dep_la_SOURCES = \
+	self-dep-plugin.c	\
+	self-dep-plugin.h
+
+libself_dep_la_LDFLAGS = $(TEST_PLUGIN_LIBTOOL_FLAGS)
+libself_dep_la_LIBADD  = $(PEAS_LIBS)
+
+noinst_DATA = self-dep.plugin
+
+EXTRA_DIST = $(noinst_DATA)
diff --git a/tests/plugins/self-dep/self-dep-plugin.c b/tests/plugins/self-dep/self-dep-plugin.c
new file mode 100644
index 0000000..b774ffe
--- /dev/null
+++ b/tests/plugins/self-dep/self-dep-plugin.c
@@ -0,0 +1,143 @@
+/*
+ * self-dep-plugin.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <libpeas/peas.h>
+
+#include "self-dep-plugin.h"
+
+struct _TestingSelfDepPluginPrivate {
+  GObject *object;
+};
+
+static void peas_activatable_iface_init (PeasActivatableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingSelfDepPlugin,
+                                testing_self_dep_plugin,
+                                PEAS_TYPE_EXTENSION_BASE,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_TYPE_ACTIVATABLE,
+                                                               peas_activatable_iface_init))
+
+enum {
+  PROP_0,
+  PROP_OBJECT
+};
+
+static void
+testing_self_dep_plugin_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  TestingSelfDepPlugin *plugin = TESTING_SELF_DEP_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      plugin->priv->object = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_self_dep_plugin_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  TestingSelfDepPlugin *plugin = TESTING_SELF_DEP_PLUGIN (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      g_value_set_object (value, plugin->priv->object);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+testing_self_dep_plugin_init (TestingSelfDepPlugin *plugin)
+{
+  plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin,
+                                              TESTING_TYPE_SELF_DEP_PLUGIN,
+                                              TestingSelfDepPluginPrivate);
+}
+
+static void
+testing_self_dep_plugin_activate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_self_dep_plugin_deactivate (PeasActivatable *activatable)
+{
+}
+
+static void
+testing_self_dep_plugin_class_init (TestingSelfDepPluginClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = testing_self_dep_plugin_set_property;
+  object_class->get_property = testing_self_dep_plugin_get_property;
+
+  g_object_class_override_property (object_class, PROP_OBJECT, "object");
+
+  g_type_class_add_private (klass, sizeof (TestingSelfDepPluginPrivate));
+}
+
+static void
+peas_activatable_iface_init (PeasActivatableInterface *iface)
+{
+  iface->activate = testing_self_dep_plugin_activate;
+  iface->deactivate = testing_self_dep_plugin_deactivate;
+}
+
+static void
+testing_self_dep_plugin_class_finalize (TestingSelfDepPluginClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+  testing_self_dep_plugin_register_type (G_TYPE_MODULE (module));
+
+  peas_object_module_register_extension_type (module,
+                                              PEAS_TYPE_ACTIVATABLE,
+                                              TESTING_TYPE_SELF_DEP_PLUGIN);
+}
diff --git a/tests/plugins/self-dep/self-dep-plugin.h b/tests/plugins/self-dep/self-dep-plugin.h
new file mode 100644
index 0000000..6927ac7
--- /dev/null
+++ b/tests/plugins/self-dep/self-dep-plugin.h
@@ -0,0 +1,55 @@
+/*
+ * self-dep-plugin.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Garrett Regier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TESTING_SELF_DEP_PLUGIN_H__
+#define __TESTING_SELF_DEP_PLUGIN_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define TESTING_TYPE_SELF_DEP_PLUGIN         (testing_self_dep_plugin_get_type ())
+#define TESTING_SELF_DEP_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TESTING_TYPE_SELF_DEP_PLUGIN, TestingSelfDepPlugin))
+#define TESTING_SELF_DEP_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TESTING_TYPE_SELF_DEP_PLUGIN, TestingSelfDepPlugin))
+#define TESTING_IS_SELF_DEP_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TESTING_TYPE_SELF_DEP_PLUGIN))
+#define TESTING_IS_SELF_DEP_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TESTING_TYPE_SELF_DEP_PLUGIN))
+#define TESTING_SELF_DEP_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TESTING_TYPE_SELF_DEP_PLUGIN, TestingSelfDepPluginClass))
+
+typedef struct _TestingSelfDepPlugin         TestingSelfDepPlugin;
+typedef struct _TestingSelfDepPluginClass    TestingSelfDepPluginClass;
+typedef struct _TestingSelfDepPluginPrivate  TestingSelfDepPluginPrivate;
+
+struct _TestingSelfDepPlugin {
+  PeasExtensionBase parent_instance;
+
+  TestingSelfDepPluginPrivate *priv;
+};
+
+struct _TestingSelfDepPluginClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+GType                 testing_self_dep_plugin_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void  peas_register_types              (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __TESTING_SELF_DEP_PLUGIN_H__ */
diff --git a/tests/plugins/self-dep/self-dep.plugin b/tests/plugins/self-dep/self-dep.plugin
new file mode 100644
index 0000000..39c13ee
--- /dev/null
+++ b/tests/plugins/self-dep/self-dep.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=self-dep
+Depends=self-dep
+IAge=2
+Name=Self Dep
+Description=This plugin can be loaded and has a dep of itself.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas
diff --git a/tests/plugins/unavailable.plugin b/tests/plugins/unavailable.plugin
new file mode 100644
index 0000000..e68221c
--- /dev/null
+++ b/tests/plugins/unavailable.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=unavailable
+Depends=does-not-exist
+IAge=2
+Name=Unavailable
+Description=This plugin cannot be loaded.
+Authors=Garrett Regier
+Copyright=Copyright © 2010 Garrett Regier
+Website=http://live.gnome.org/Libpeas



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]