plugind: fixes/changes after tests and reviews
authorImran Zaman <imran.zaman@linux.intel.com>
Mon, 6 May 2013 17:12:48 +0000 (20:12 +0300)
committerImran Zaman <imran.zaman@linux.intel.com>
Wed, 15 May 2013 12:29:06 +0000 (15:29 +0300)
17 files changed:
include/gsignond/gsignond-pipe-stream.h
src/common/gsignond-pipe-stream.c
src/daemon/plugins/gsignond-plugin-proxy-factory.c
src/daemon/plugins/gsignond-plugin-remote-private.h [new file with mode: 0644]
src/daemon/plugins/gsignond-plugin-remote.c
src/daemon/plugins/plugind/Makefile.am
src/daemon/plugins/plugind/gsignond-plugin-daemon.c
src/plugins/password/gsignond-password-plugin.c
test/Makefile.am
test/common/Makefile.am
test/common/commontest.c
test/daemon/Makefile.am
test/db/Makefile.am
test/plugins/Makefile.am
test/plugins/pluginproxytest.c
test/plugins/pluginremotetest.c [new file with mode: 0644]
test/valgrind_common.mk

index 05d1c0c..6a1882e 100644 (file)
@@ -71,7 +71,8 @@ gsignond_pipe_stream_get_type (void);
 GSignondPipeStream *
 gsignond_pipe_stream_new (
         gint in_fd,
-        gint out_fd);
+        gint out_fd,
+        gboolean close_fds);
 
 G_END_DECLS
 
index 29901c3..dae78a5 100644 (file)
@@ -57,25 +57,28 @@ _gsignond_pipe_stream_dispose (GObject *gobject)
 {
     g_return_if_fail (GSIGNOND_IS_PIPE_STREAM (gobject));
 
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (gsignond_pipe_stream_parent_class)->dispose (gobject);
+
+}
+
+static void
+_gsignond_pipe_stream_finalize (GObject *gobject)
+{
     GSignondPipeStream *stream = GSIGNOND_PIPE_STREAM (gobject);
 
+    /* g_io_stream needs streams to be valid in its dispose still
+     */
     if (stream->priv->input_stream) {
-        g_object_unref (stream->priv->input_stream);
+        g_clear_object (&stream->priv->input_stream);
         stream->priv->input_stream = NULL;
     }
 
     if (stream->priv->output_stream) {
-        g_object_unref (stream->priv->output_stream);
+        g_clear_object (&stream->priv->output_stream);
         stream->priv->output_stream = NULL;
     }
 
-    /* Chain up to the parent class */
-    G_OBJECT_CLASS (gsignond_pipe_stream_parent_class)->dispose (gobject);
-}
-
-static void
-_gsignond_pipe_stream_finalize (GObject *gobject)
-{
     G_OBJECT_CLASS (gsignond_pipe_stream_parent_class)->finalize (gobject);
 }
 
@@ -106,15 +109,16 @@ gsignond_pipe_stream_init (GSignondPipeStream *self)
 GSignondPipeStream *
 gsignond_pipe_stream_new (
         gint in_fd,
-        gint out_fd)
+        gint out_fd,
+        gboolean close_fds)
 {
     GSignondPipeStream *stream = GSIGNOND_PIPE_STREAM (g_object_new (
             GSIGNOND_TYPE_PIPE_STREAM, NULL));
     if (stream) {
-        stream->priv->input_stream = (GInputStream *)
-                    g_unix_input_stream_new (in_fd, TRUE);
-        stream->priv->output_stream = (GOutputStream *)
-                    g_unix_output_stream_new (out_fd, TRUE);
+        stream->priv->input_stream = G_INPUT_STREAM (
+                g_unix_input_stream_new (in_fd, close_fds));
+        stream->priv->output_stream = G_OUTPUT_STREAM (
+                g_unix_output_stream_new (out_fd, close_fds));
     }
     return stream;
 }
index 42340e2..98efb0c 100644 (file)
@@ -57,10 +57,6 @@ static void _enumerate_plugins(GSignondPluginProxyFactory* self)
     g_dir_rewind(plugin_dir);
     
     self->methods = g_malloc0(sizeof(gchar*) * (n_plugins + 1));
-    self->mechanisms = g_hash_table_new_full((GHashFunc)g_str_hash,
-                                             (GEqualFunc)g_str_equal,
-                                             (GDestroyNotify)g_free,
-                                             (GDestroyNotify)g_strfreev);
 
     DBG ("enumerate plugins in %s (factory=%p)",
          gsignond_config_get_string (self->config,
@@ -76,8 +72,8 @@ static void _enumerate_plugins(GSignondPluginProxyFactory* self)
             g_str_has_suffix(plugin_soname, ".so")) {
             gchar* plugin_name = g_strndup(plugin_soname+3, 
                 strlen(plugin_soname) - 6);
-            GSignondPlugin* plugin = gsignond_load_plugin(
-                self->config, plugin_name);
+            GSignondPlugin* plugin = GSIGNOND_PLUGIN (
+                    gsignond_plugin_remote_new (self->config, plugin_name));
             if (plugin != NULL) {
                 gchar* plugin_type;
                 gchar** mechanisms;
@@ -221,6 +217,11 @@ gsignond_plugin_proxy_factory_class_init (GSignondPluginProxyFactoryClass *klass
 static void
 gsignond_plugin_proxy_factory_init (GSignondPluginProxyFactory *self)
 {
+    self->mechanisms = g_hash_table_new_full((GHashFunc)g_str_hash,
+                                             (GEqualFunc)g_str_equal,
+                                             (GDestroyNotify)g_free,
+                                             (GDestroyNotify)g_strfreev);
+
     self->plugins = g_hash_table_new_full ((GHashFunc)g_str_hash,
                                            (GEqualFunc)g_str_equal,
                                            (GDestroyNotify)g_free,
@@ -303,17 +304,18 @@ gsignond_plugin_proxy_factory_get_plugin_mechanisms(
     const gchar **mechanisms = NULL;
     mechanisms = g_hash_table_lookup(factory->mechanisms, plugin_type);
     if (mechanisms == NULL) {
-       GSignondPlugin* plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new (
-               factory->config, plugin_type));
-       if (plugin != NULL) {
-               gchar **mechs = NULL;
-               g_object_get (plugin, "mechanisms", &mechs, NULL);
-               if (mechs != NULL) {
-                       g_hash_table_insert(factory->mechanisms, g_strdup(plugin_type),
-                               mechs);
-                       mechanisms = (const gchar **)mechs;
-               }
-       }
+        GSignondPlugin* plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new (
+                factory->config, plugin_type));
+        if (plugin != NULL) {
+            gchar **mechs = NULL;
+            g_object_get (plugin, "mechanisms", &mechs, NULL);
+            if (mechs != NULL) {
+                g_hash_table_insert(factory->mechanisms, g_strdup(plugin_type),
+                        mechs);
+                mechanisms = (const gchar **)mechs;
+            }
+            g_object_unref (plugin);
+        }
     }
     return mechanisms;
 }
diff --git a/src/daemon/plugins/gsignond-plugin-remote-private.h b/src/daemon/plugins/gsignond-plugin-remote-private.h
new file mode 100644 (file)
index 0000000..c1d03c1
--- /dev/null
@@ -0,0 +1,58 @@
+/* vi: set et sw=4 ts=4 cino=t0,(0: */
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of gsignond
+ *
+ * Copyright (C) 2013 Intel Corporation.
+ *
+ * Contact: Imran Zaman <imran.zaman@linux.intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __GSIGNOND_PLUGIN_REMOTE_PRIVATE_H__
+#define __GSIGNOND_PLUGIN_REMOTE_PRIVATE_H__
+
+#include <glib.h>
+#include <daemon/dbus/gsignond-dbus-remote-plugin-gen.h>
+#include "daemon/dbus/gsignond-dbus.h"
+
+G_BEGIN_DECLS
+
+struct _GSignondPluginRemotePrivate
+{
+    GDBusConnection   *connection;
+    GSignondDbusRemotePlugin *dbus_plugin_proxy;
+    GIOChannel *err_watch_ch;
+    gchar *plugin_type;
+    gchar **plugin_mechanisms;
+    GPid cpid;
+    guint child_watch_id;
+    guint err_watch_id;
+
+    /* Signals */
+    guint signal_response;
+    guint signal_response_final;
+    guint signal_store;
+    guint signal_error;
+    guint signal_user_action_required;
+    guint signal_refreshed;
+    guint signal_status_changed;
+};
+
+G_END_DECLS
+
+#endif /* __GSIGNOND_PLUGIN_REMOTE_PRIVATE_H__ */
index 3d5c69d..40234f0 100644 (file)
@@ -28,6 +28,7 @@
 #include "gsignond/gsignond-pipe-stream.h"
 #include "gsignond/gsignond-plugin-interface.h"
 #include "daemon/dbus/gsignond-dbus.h"
+#include "gsignond-plugin-remote-private.h"
 #include "gsignond-plugin-remote.h"
 
 enum
@@ -38,29 +39,6 @@ enum
     N_PROPERTIES
 };
 
-//static GParamSpec *properties[N_PROPERTIES];
-
-struct _GSignondPluginRemotePrivate
-{
-    GDBusConnection   *connection;
-    GSignondDbusRemotePlugin *dbus_plugin_proxy;
-    GIOChannel *err_watch_ch;
-    gchar *plugin_type;
-    gchar **plugin_mechanisms;
-    GPid cpid;
-    guint child_watch_id;
-    guint err_watch_id;
-
-    /* Signals */
-    guint signal_response;
-    guint signal_response_final;
-    guint signal_store;
-    guint signal_error;
-    guint signal_user_action_required;
-    guint signal_refreshed;
-    guint signal_status_changed;
-};
-
 static void
 gsignond_plugin_remote_interface_init (
         GSignondPluginInterface *iface);
@@ -107,7 +85,10 @@ gsignond_plugin_remote_get_property (
                 if (error) {
                     DBG ("Plugin type retrieval error :: %s", error->message);
                     g_error_free (error);
-                    self->priv->plugin_type = NULL;
+                    if (self->priv->plugin_type) {
+                        g_free (self->priv->plugin_type);
+                        self->priv->plugin_type = NULL;
+                    }
                 }
             }
             g_value_set_string (value, self->priv->plugin_type);
@@ -123,7 +104,10 @@ gsignond_plugin_remote_get_property (
                     DBG ("Plugin mechanisms retrieval error :: %s",
                             error->message);
                     g_error_free (error);
-                    self->priv->plugin_mechanisms = NULL;
+                    if (self->priv->plugin_mechanisms) {
+                        g_strfreev (self->priv->plugin_mechanisms);
+                        self->priv->plugin_mechanisms = NULL;
+                    }
                 }
             }
             g_value_set_boxed (value, self->priv->plugin_mechanisms);
@@ -519,14 +503,22 @@ _error_watch_cb (
 
     GSignondPluginRemote *plugin = (GSignondPluginRemote*)data;
 
-    if (condition == G_IO_HUP || condition == G_IO_ERR ||
-            condition == G_IO_NVAL) {
+    if (condition == G_IO_HUP || condition == G_IO_NVAL) {
         g_io_channel_shutdown (plugin->priv->err_watch_ch, FALSE, NULL);
         g_io_channel_unref (plugin->priv->err_watch_ch);
         plugin->priv->err_watch_ch = NULL;
         g_source_remove (plugin->priv->err_watch_id);
         DBG ("Plugind (%s) is down",
                 plugin->priv->plugin_type ? plugin->priv->plugin_type : "");
+
+        if (plugin->priv->cpid > 0 &&
+            kill (plugin->priv->cpid, 0) != 0) {
+            if (plugin->priv->child_watch_id) {
+                g_source_remove (plugin->priv->child_watch_id);
+                plugin->priv->child_watch_id = 0;
+            }
+            plugin->priv->cpid = 0;
+        }
         return FALSE;
     }
 
@@ -594,7 +586,7 @@ gsignond_plugin_remote_new (
             GSIGNOND_CONFIG_GENERAL_PLUGINS_DIR), plugin_type);
     argv[2] = g_strdup(plugin_type);
     ret = g_spawn_async_with_pipes (NULL, argv, NULL,
-            G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL,
+            G_SPAWN_DO_NOT_REAP_CHILD, NULL,
             NULL, &cpid, &cin_fd, &cout_fd, &cerr_fd, &error);
     g_strfreev (argv);
     if (ret == FALSE || (kill(cpid, 0) != 0)) {
@@ -614,7 +606,7 @@ gsignond_plugin_remote_new (
             plugin_type);
 
     /* Create dbus connection */
-    stream = gsignond_pipe_stream_new (cout_fd, cin_fd);
+    stream = gsignond_pipe_stream_new (cout_fd, cin_fd, TRUE);
     plugin->priv->connection = g_dbus_connection_new_sync (G_IO_STREAM (stream),
             NULL, G_DBUS_CONNECTION_FLAGS_NONE, NULL, NULL, NULL);
     g_object_unref (stream);
index d4ca2eb..ac8da86 100644 (file)
@@ -1,11 +1,26 @@
 SUBDIRS=
 NULL=
 
+lib_LTLIBRARIES = libgsignond-plugind-daemon.la
+
+libgsignond_plugind_daemon_la_CPPFLAGS = \
+    -I$(top_srcdir) \
+    -I$(top_srcdir)/src \
+    -I$(top_srcdir)/include \
+    $(GSIGNOND_CFLAGS)
+
+libgsignond_plugind_daemon_la_LIBADD =    \
+        $(top_srcdir)/src/common/libgsignond-common.la \
+        $(top_srcdir)/src/daemon/dbus/libgsignond-dbus-glue.la \
+        $(GSIGNOND_LIBS)
+
+libgsignond_plugind_daemon_la_SOURCES = \
+   gsignond-plugin-daemon.c
+
 bin_PROGRAMS = gsignond-plugind
 
 gsignond_plugind_SOURCES = \
     main.c \
-    gsignond-plugin-daemon.c \
     $(NULL)
 
 gsignond_plugind_CFLAGS = \
@@ -16,8 +31,7 @@ gsignond_plugind_CFLAGS = \
     $(NULL)
 
 gsignond_plugind_LDADD = \
-    $(top_srcdir)/src/common/libgsignond-common.la \
-    $(top_srcdir)/src/daemon/dbus/libgsignond-dbus-glue.la \
+    $(top_srcdir)/src/daemon/plugins/plugind/libgsignond-plugind-daemon.la \
     $(GSIGNOND_LIBS) \
     $(NULL)
 
index 6cb8cea..2acd9cc 100644 (file)
@@ -381,7 +381,7 @@ gsignond_plugin_daemon_new (
     daemon->priv->plugin_type = g_strdup (plugin_type);
 
     /* Create dbus connection */
-    stream = gsignond_pipe_stream_new (0, 1);
+    stream = gsignond_pipe_stream_new (0, 1, FALSE);
     daemon->priv->connection = g_dbus_connection_new_sync (G_IO_STREAM (stream),
             NULL, G_DBUS_CONNECTION_FLAGS_NONE, NULL, NULL, NULL);
     g_object_unref (stream);
index a4f64b5..90bf757 100644 (file)
@@ -91,6 +91,7 @@ static void gsignond_password_plugin_user_action_finished (
                                 "userActionFinished did not return an error value");
         gsignond_plugin_error (self, error); 
         g_error_free(error);
+        return;
     }
     const gchar* username = gsignond_signonui_data_get_username(session_data);
     const gchar* secret = gsignond_signonui_data_get_password(session_data);
index 1bd0f7b..00098b7 100644 (file)
@@ -1,7 +1,7 @@
-SUBDIRS=common daemon db plugins
+SUBDIRS = common daemon db plugins
 
-VALGRIND_TESTS_DISABLE=
+VALGRIND_TESTS_DISABLE =
 valgrind: $(SUBDIRS)
        for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(SUBDIRS)); do \
-               cd $$t; $(MAKE) valgrind; \
+               cd $$t; $(MAKE) valgrind; cd ..;\
        done;
index e940f71..834a9c8 100644 (file)
@@ -1,9 +1,9 @@
 TESTS = commontest
 TESTS_ENVIRONMENT=
 VALGRIND_TESTS_DISABLE=
-include $(top_srcdir)/test/valgrind_common.mk
 
 check_PROGRAMS = commontest
+include $(top_srcdir)/test/valgrind_common.mk
 commontest_SOURCES = commontest.c
 commontest_CFLAGS = \
     $(GSIGNOND_CFLAGS) \
index 0207848..98c0be6 100644 (file)
 
 #include <check.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <glib-unix.h>
 #include <gsignond/gsignond-session-data.h>
 #include <gsignond/gsignond-plugin-loader.h>
 #include <gsignond/gsignond-error.h>
 #include <gsignond/gsignond-log.h>
+#include <gsignond/gsignond-pipe-stream.h>
 
+START_TEST (test_pipe_stream)
+{
+    GSignondPipeStream *stream = NULL;
+    gint pipefd[2];
+    fail_unless (pipe (pipefd) == 0);
+    stream = gsignond_pipe_stream_new (pipefd[0], pipefd[1], TRUE);
+    fail_if (stream == NULL);
+    g_object_unref (stream);
+}
+END_TEST
 
 START_TEST (test_session_data)
 {
@@ -114,13 +128,13 @@ START_TEST (test_plugin_loader)
 }
 END_TEST
 
-
 Suite* common_suite (void)
 {
     Suite *s = suite_create ("Common library");
     
     /* Core test case */
     TCase *tc_core = tcase_create ("Tests");
+    tcase_add_test (tc_core, test_pipe_stream);
     tcase_add_test (tc_core, test_session_data);
     tcase_add_test (tc_core, test_plugin_loader);
     suite_add_tcase (s, tc_core);
index 8acf902..6fdd2c5 100644 (file)
@@ -5,9 +5,9 @@ TESTS = test-daemon-setup.sh
 endif
 TESTS_ENVIRONMENT=
 VALGRIND_TESTS_DISABLE=
-include $(top_srcdir)/test/valgrind_common.mk
 
 check_PROGRAMS = daemontest
+include $(top_srcdir)/test/valgrind_common.mk
 
 daemontest_SOURCES = daemon-test.c
 
index 7397f0e..485bfbc 100644 (file)
@@ -1,9 +1,10 @@
 TESTS = dbtest
 TESTS_ENVIRONMENT=
 VALGRIND_TESTS_DISABLE=
-include $(top_srcdir)/test/valgrind_common.mk
 
 check_PROGRAMS = dbtest
+include $(top_srcdir)/test/valgrind_common.mk
+
 dbtest_SOURCES = dbtest.c
 dbtest_CFLAGS = \
     $(GSIGNOND_CFLAGS) \
index 7a20aac..5b38751 100644 (file)
@@ -1,9 +1,10 @@
-TESTS = digestplugintest passwordplugintest pluginproxytest
+TESTS = digestplugintest passwordplugintest pluginproxytest pluginremotetest
 TESTS_ENVIRONMENT= SSO_PLUGINS_DIR=$(top_builddir)/src/plugins/.libs
 VALGRIND_TESTS_DISABLE =
-include $(top_srcdir)/test/valgrind_common.mk
     
-check_PROGRAMS = digestplugintest passwordplugintest pluginproxytest
+check_PROGRAMS = digestplugintest passwordplugintest pluginproxytest pluginremotetest
+include $(top_srcdir)/test/valgrind_common.mk
+
 digestplugintest_SOURCES = digestplugintest.c
 digestplugintest_CFLAGS = \
     $(GSIGNOND_CFLAGS) \
@@ -44,4 +45,18 @@ pluginproxytest_LDADD = \
     $(GSIGNOND_LIBS) \
     $(CHECK_LIBS)
 
+pluginremotetest_SOURCES = pluginremotetest.c
+pluginremotetest_CFLAGS = \
+    $(GSIGNOND_CFLAGS) \
+    $(CHECK_CFLAGS) \
+    -I$(top_srcdir)/src \
+    -I$(top_srcdir)/src/daemon/plugins \
+    -I$(top_srcdir)/src/daemon/plugins/plugind \
+    -I$(top_srcdir)/include/
 
+pluginremotetest_LDADD = \
+    $(top_builddir)/src/common/libgsignond-common.la \
+    $(top_builddir)/src/daemon/plugins/libgsignond-plugins.la \
+    $(top_builddir)/src/daemon/plugins/plugind/libgsignond-plugind-daemon.la \
+    $(GSIGNOND_LIBS) \
+    $(CHECK_LIBS)
index 614e030..93f8485 100644 (file)
@@ -48,7 +48,7 @@ _stop_mainloop ()
 }
 
 static void
-_start_mainloop ()
+_run_mainloop ()
 {
     g_main_loop_run (main_loop);
 }
@@ -90,8 +90,6 @@ static void
 gsignond_auth_session_init (
         GSignondAuthSession *self)
 {
-
-    
 }
 
 static void
@@ -241,20 +239,23 @@ check_plugin_proxy(
 {
     gchar* ptype = NULL;
     gchar** pmechanisms = NULL;
+    gint i = 0;
 
     fail_if(proxy == NULL);
 
     g_object_get(proxy, "type", &ptype, "mechanisms", &pmechanisms, NULL);
     fail_unless(g_strcmp0(ptype, type) == 0);
-    if (pmechanisms == NULL) {
-        fail_unless (mechanisms[0] == NULL);
-    } else {
-        fail_unless(g_strcmp0(pmechanisms[0], mechanisms[0]) == 0);
-        fail_unless(pmechanisms[1] == NULL && mechanisms[1] == NULL);
-    }
-
     g_free(ptype);
-    g_strfreev(pmechanisms);
+
+    guint len = g_strv_length (pmechanisms);
+    fail_unless (len == g_strv_length (mechanisms));
+
+    for (i=0; i<len; i++) {
+        fail_unless(g_strcmp0(pmechanisms[i], mechanisms[i]) == 0);
+    }
+    if (pmechanisms) {
+        g_strfreev(pmechanisms);
+    }
 }
 
 START_TEST (test_pluginproxy_create)
@@ -302,7 +303,7 @@ START_TEST (test_pluginproxy_process)
     gsignond_plugin_proxy_process(proxy, test_auth_session, data, "password",
             proxy);
 
-    _start_mainloop ();
+    _run_mainloop ();
 
     fail_if(testing_proxy_process);
     
@@ -334,7 +335,7 @@ START_TEST (test_pluginproxy_process_cancel)
     gsignond_plugin_proxy_process(proxy, test_auth_session, data, "mech1",
             proxy);
 
-    _start_mainloop ();
+    _run_mainloop ();
 
     fail_if(testing_proxy_process_cancel);
     
@@ -367,7 +368,7 @@ START_TEST (test_pluginproxy_process_queue)
     
     gsignond_plugin_proxy_process(proxy, test_auth_session, data, "password",
             proxy);
-    _start_mainloop ();
+    _run_mainloop ();
 
     fail_if(testing_proxy_process_queue);
     fail_if(proxy_process_queue_results < 3);
@@ -398,7 +399,7 @@ START_TEST (test_pluginproxy_process_queue_cancel)
     gsignond_plugin_proxy_process(proxy, test_auth_session, data, "mech1",
             proxy);
 
-    _start_mainloop ();
+    _run_mainloop ();
 
     fail_if(testing_proxy_process_queue_cancel);
     fail_if(proxy_process_queue_cancel_results != 10);
diff --git a/test/plugins/pluginremotetest.c b/test/plugins/pluginremotetest.c
new file mode 100644 (file)
index 0000000..bb2be31
--- /dev/null
@@ -0,0 +1,566 @@
+/* vi: set et sw=4 ts=4 cino=t0,(0: */
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of gsignond
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <check.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "gsignond-plugin-remote-private.h"
+#include "gsignond-plugin-remote.h"
+#include "plugind/gsignond-plugin-daemon.h"
+#include <gsignond/gsignond-plugin-interface.h>
+#include <gsignond/gsignond-error.h>
+#include <gsignond/gsignond-config.h>
+#include <gsignond/gsignond-log.h>
+
+static GMainLoop *main_loop = NULL;
+guint child_watch_id = 0;
+
+typedef struct _GSignondAuthSession GSignondAuthSession;
+typedef struct _GSignondAuthSessionClass GSignondAuthSessionClass;
+
+struct _GSignondAuthSession
+{
+    GObject parent;
+};
+
+struct _GSignondAuthSessionClass
+{
+    GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (GSignondAuthSession, gsignond_auth_session, G_TYPE_OBJECT);
+
+static void
+_stop_mainloop ()
+{
+    if (main_loop) {
+        g_main_loop_quit (main_loop);
+    }
+}
+
+static void
+_run_mainloop ()
+{
+    g_main_loop_run (main_loop);
+}
+
+static void
+_setup ()
+{
+    g_type_init ();
+    if (main_loop == NULL) {
+        main_loop = g_main_loop_new (NULL, FALSE);
+    }
+}
+
+static void
+_teardown ()
+{
+    if (main_loop) {
+        _stop_mainloop ();
+        g_main_loop_unref (main_loop);
+        main_loop = NULL;
+    }
+}
+
+static void
+gsignond_auth_session_init (
+        GSignondAuthSession *self)
+{
+}
+
+static void
+gsignond_auth_session_class_init (
+        GSignondAuthSessionClass *klass)
+{
+}
+
+void
+gsignond_auth_session_notify_process_result (
+        GSignondAuthSession *iface,
+        GSignondSessionData *result,
+        gpointer user_data)
+{
+}
+
+void
+gsignond_auth_session_notify_process_error (
+        GSignondAuthSession *iface,
+        const GError *error,
+        gpointer user_data)
+{
+}
+
+void
+gsignond_auth_session_notify_store (
+        GSignondAuthSession *self,
+        GSignondSessionData *session_data)
+{
+}
+
+void
+gsignond_auth_session_notify_user_action_required (
+        GSignondAuthSession *self,
+        GSignondSignonuiData *session_data)
+{
+}
+
+void
+gsignond_auth_session_notify_refreshed (
+        GSignondAuthSession *self,
+        GSignondSignonuiData *session_data)
+{
+}
+
+void
+gsignond_auth_session_notify_state_changed (
+        GSignondAuthSession *self,
+        gint state,
+        const gchar *message,
+        gpointer user_data)
+{
+}
+
+static void
+check_plugin(
+        GSignondPlugin* plugin)
+{
+    gchar* type;
+    gchar** mechanisms;
+
+    fail_if(plugin == NULL);
+    
+    g_object_get(plugin, "type", &type, "mechanisms", &mechanisms, NULL);
+    
+    fail_unless(g_strcmp0(type, "password") == 0);
+    fail_unless(g_strcmp0(mechanisms[0], "password") == 0);
+    fail_unless(mechanisms[1] == NULL);
+    
+    g_free(type);
+    g_strfreev(mechanisms);
+}
+
+static void
+response_callback(
+        GSignondPlugin* plugin,
+        GSignondSessionData* result,
+        gpointer user_data)
+{
+    DBG ("");
+    GSignondSessionData** user_data_p = user_data;
+    *user_data_p = gsignond_dictionary_copy(result);
+    _stop_mainloop ();
+}
+
+static void
+user_action_required_callback(
+        GSignondPlugin* plugin,
+        GSignondSignonuiData* ui_request,
+        gpointer user_data)
+{
+    DBG ("");
+    GSignondSignonuiData** user_data_p = user_data;
+    *user_data_p = gsignond_dictionary_copy(ui_request);
+    _stop_mainloop ();
+}
+
+static void
+error_callback(
+        GSignondPlugin* plugin,
+        GError* error,
+        gpointer user_data)
+{
+    DBG ("");
+    GError** user_data_p = user_data;
+    *user_data_p = g_error_copy(error);
+    _stop_mainloop ();
+}
+
+START_TEST (test_pluginremote_create)
+{
+    DBG ("");
+    GSignondPlugin *plugin = NULL;
+    const gchar *plugin_type = "password";
+
+    GSignondConfig* config = gsignond_config_new ();
+    fail_if (config == NULL);
+
+    plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new(config, plugin_type));
+
+    check_plugin (plugin);
+    g_object_unref (config);
+    g_object_unref (plugin);
+}
+END_TEST
+
+static void
+_child_watch_cb (
+        GPid  pid,
+        gint  status,
+        gpointer data)
+{
+    DBG ("plugind GONE");
+    _stop_mainloop ();
+    g_source_remove (child_watch_id);
+    child_watch_id = 0;
+}
+
+START_TEST (test_pluginremote_plugind_create)
+{
+    DBG ("");
+    GSignondPlugin *plugin = NULL;
+    const gchar *plugin_type = "password";
+    GSignondPluginRemotePrivate* priv = NULL;
+    gint cpid = 0;
+
+    GSignondConfig* config = gsignond_config_new ();
+    fail_if (config == NULL);
+    
+    plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new(config, plugin_type));
+    fail_if (plugin == NULL);
+    priv = (GSignondPluginRemotePrivate *)GSIGNOND_PLUGIN_REMOTE (plugin)->priv;
+
+    fail_unless (priv->child_watch_id > 0);
+    fail_unless (priv->cpid > 0);
+    cpid = priv->cpid;
+
+    child_watch_id = g_child_watch_add (cpid,
+            (GChildWatchFunc)_child_watch_cb, plugin);
+
+    g_object_unref (plugin);
+    g_object_unref (config);
+
+    _run_mainloop ();
+
+    fail_unless (child_watch_id == 0);
+    fail_unless (kill (cpid, 0) != 0);
+}
+END_TEST
+
+START_TEST (test_pluginremote_plugind_kill)
+{
+    DBG ("");
+    GSignondPlugin *plugin = NULL;
+    const gchar *plugin_type = "password";
+    GSignondPluginRemotePrivate* priv = NULL;
+
+    GSignondConfig* config = gsignond_config_new ();
+    fail_if (config == NULL);
+
+    plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new(config, plugin_type));
+    fail_if (plugin == NULL);
+    priv = (GSignondPluginRemotePrivate *)GSIGNOND_PLUGIN_REMOTE (plugin)->priv;
+
+    fail_unless (priv->child_watch_id > 0);
+    fail_unless (priv->cpid > 0);
+    fail_unless (kill (priv->cpid, 0) == 0);
+
+    child_watch_id = g_child_watch_add (priv->cpid,
+            (GChildWatchFunc)_child_watch_cb, plugin);
+
+    kill (priv->cpid, SIGTERM);
+    _run_mainloop ();
+
+    fail_unless (child_watch_id == 0);
+
+    g_object_unref (plugin);
+    g_object_unref (config);
+}
+END_TEST
+
+START_TEST (test_pluginremote_request)
+{
+    DBG ("");
+    GSignondPlugin *plugin = NULL;
+    const gchar *plugin_type = "password";
+
+    GSignondConfig* config = gsignond_config_new ();
+    fail_if(config == NULL);
+    
+    plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new(config, plugin_type));
+    fail_if(plugin == NULL);
+
+    GSignondSessionData* result = NULL;
+    GSignondSignonuiData* ui_action = NULL;
+    GError* error = NULL;
+    gboolean bool_res;
+
+    g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback),
+            &result);
+    g_signal_connect(plugin, "user-action-required", 
+                     G_CALLBACK(user_action_required_callback), &ui_action);
+    g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error);
+
+    GSignondSessionData* data = gsignond_dictionary_new ();
+
+    // username empty, password not empty
+    gsignond_session_data_set_secret(data, "megapassword");
+    gsignond_plugin_request_initial(plugin, data, "password");
+    _run_mainloop ();
+
+    fail_if(result == NULL);    
+    fail_if(ui_action != NULL);
+    fail_if(error != NULL);
+    fail_if(gsignond_session_data_get_username(result) != NULL);
+    fail_if(g_strcmp0(
+        gsignond_session_data_get_secret(result), "megapassword") != 0);
+    gsignond_dictionary_unref(result);
+    result = NULL;
+    
+    // username and password not empty
+    gsignond_session_data_set_username(data, "megauser");
+    gsignond_plugin_request_initial(plugin, data, "password");
+    _run_mainloop ();
+
+    fail_if(result == NULL);    
+    fail_if(ui_action != NULL);
+    fail_if(error != NULL);
+    fail_if(g_strcmp0(
+        gsignond_session_data_get_username(result), "megauser") != 0);
+    fail_if(g_strcmp0(
+        gsignond_session_data_get_secret(result), "megapassword") != 0);
+    gsignond_dictionary_unref(result);
+    result = NULL;
+    
+    //username and password empty
+    gsignond_dictionary_unref(data);
+    data = gsignond_dictionary_new();
+    gsignond_plugin_request_initial(plugin, data, "password");
+    _run_mainloop ();
+
+    fail_if(result != NULL);    
+    fail_if(ui_action == NULL);
+    fail_if(error != NULL);
+    fail_if(gsignond_signonui_data_get_query_username(ui_action, &bool_res)
+            == FALSE);
+    fail_if(bool_res == FALSE);
+    fail_if(gsignond_signonui_data_get_query_password(ui_action, &bool_res)
+            == FALSE);
+    fail_if(bool_res == FALSE);    
+    gsignond_dictionary_unref(ui_action);
+    ui_action = NULL;
+    
+    //username not empty, password empty
+    gsignond_session_data_set_username(data, "megauser");
+    gsignond_plugin_request_initial(plugin, data, "password");
+    _run_mainloop ();
+
+    fail_if(result != NULL);    
+    fail_if(ui_action == NULL);
+    fail_if(error != NULL);
+    fail_if(gsignond_signonui_data_get_query_username(ui_action, &bool_res)
+            == FALSE);
+    fail_if(bool_res == TRUE);
+    fail_if(gsignond_signonui_data_get_query_password(ui_action, &bool_res)
+            == FALSE);
+    fail_if(bool_res == FALSE);    
+    gsignond_dictionary_unref(ui_action);
+    ui_action = NULL;
+    
+    gsignond_dictionary_unref(data);
+
+    g_object_unref(config);
+    g_object_unref(plugin);
+}
+END_TEST
+
+START_TEST (test_pluginremote_user_action_finished)
+{
+    DBG ("");
+    GSignondPlugin *plugin = NULL;
+    const gchar *plugin_type = "password";
+
+    GSignondConfig* config = gsignond_config_new ();
+    fail_if(config == NULL);
+    
+    plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new(config, plugin_type));
+    fail_if(plugin == NULL);
+
+    GSignondSessionData* result = NULL;
+    GSignondSignonuiData* ui_action = NULL;
+    GError* error = NULL;
+
+    g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback),
+            &result);
+    g_signal_connect(plugin, "user-action-required", 
+                     G_CALLBACK(user_action_required_callback), &ui_action);
+    g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error);
+
+    GSignondSignonuiData* data = gsignond_dictionary_new();
+    
+    //empty data
+    gsignond_plugin_user_action_finished(plugin, data);
+    _run_mainloop ();
+
+    fail_if(result != NULL);    
+    fail_if(ui_action != NULL);
+    fail_if(error == NULL);
+    fail_unless (error->code == GSIGNOND_ERROR_USER_INTERACTION);
+    g_error_free(error);
+    error = NULL;
+    
+    // correct values
+    gsignond_signonui_data_set_username(data, "megauser");
+    gsignond_signonui_data_set_password(data, "megapassword");
+    gsignond_signonui_data_set_query_error(data, SIGNONUI_ERROR_NONE);
+    gsignond_plugin_user_action_finished(plugin, data);
+    _run_mainloop ();
+
+    fail_if(result == NULL);    
+    fail_if(ui_action != NULL);
+    fail_if(error != NULL);
+    fail_if(g_strcmp0(
+        gsignond_session_data_get_username(result), "megauser") != 0);
+    fail_if(g_strcmp0(
+        gsignond_session_data_get_secret(result), "megapassword") != 0);
+    gsignond_dictionary_unref(result);
+    result = NULL;
+
+    // user canceled
+    gsignond_signonui_data_set_query_error(data, SIGNONUI_ERROR_CANCELED);
+    gsignond_plugin_user_action_finished(plugin, data);
+    _run_mainloop ();
+
+    fail_if(result != NULL);    
+    fail_if(ui_action != NULL);
+    fail_if(error == NULL);
+    fail_unless (error->code == GSIGNOND_ERROR_SESSION_CANCELED);
+    g_error_free(error);
+    error = NULL;
+
+    // error in ui request
+    gsignond_signonui_data_set_query_error(data, SIGNONUI_ERROR_GENERAL);
+    gsignond_plugin_user_action_finished(plugin, data);
+    _run_mainloop ();
+
+    fail_if(result != NULL);    
+    fail_if(ui_action != NULL);
+    fail_if(error == NULL);
+    fail_unless (error->code == GSIGNOND_ERROR_USER_INTERACTION);
+    g_error_free(error);
+    error = NULL;
+    
+    gsignond_dictionary_unref(data);
+
+    g_object_unref(config);
+    g_object_unref(plugin);
+}
+END_TEST
+
+START_TEST (test_pluginremote_refresh)
+{
+    DBG ("");
+    GSignondPlugin *plugin = NULL;
+    const gchar *plugin_type = "password";
+
+    GSignondConfig* config = gsignond_config_new ();
+    fail_if(config == NULL);
+    
+    plugin = GSIGNOND_PLUGIN (gsignond_plugin_remote_new(config, plugin_type));
+    fail_if(plugin == NULL);
+
+    GSignondSessionData* result = NULL;
+    GError* error = NULL;
+
+    g_signal_connect(plugin, "refreshed", G_CALLBACK(response_callback),
+            &result);
+    g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error);
+
+    GSignondSessionData* data = gsignond_dictionary_new();
+    gsignond_plugin_refresh(plugin, data);
+    _run_mainloop ();
+
+    fail_if(result == NULL);    
+    fail_if(error != NULL);
+    gsignond_dictionary_unref(result);
+    result = NULL;
+    
+    gsignond_dictionary_unref(data);
+
+    g_object_unref(config);
+    g_object_unref(plugin);
+}
+END_TEST
+
+START_TEST (test_plugind_daemon)
+{
+    DBG ("");
+    GSignondPluginDaemon *daemon = NULL;
+    const gchar *plugin_type = "password";
+
+    GSignondConfig* config = gsignond_config_new ();
+    fail_if(config == NULL);
+
+    gchar *plugin_path = g_module_build_path (gsignond_config_get_string (
+                config, GSIGNOND_CONFIG_GENERAL_PLUGINS_DIR), "nonexisting");
+    fail_if (plugin_path == NULL);
+    daemon = gsignond_plugin_daemon_new (plugin_path, "nonexisting");
+    g_free (plugin_path);
+    fail_if (daemon != NULL);
+
+    plugin_path = g_module_build_path (gsignond_config_get_string (
+            config, GSIGNOND_CONFIG_GENERAL_PLUGINS_DIR), plugin_type);
+    fail_if (plugin_path == NULL);
+    daemon = gsignond_plugin_daemon_new (plugin_path, plugin_type);
+    g_free (plugin_path);
+    fail_if (daemon == NULL);
+    g_object_unref (daemon);
+    daemon = NULL;
+    g_object_unref(config);
+}
+END_TEST
+
+Suite* pluginremote_suite (void)
+{
+    Suite *s = suite_create ("Plugin remote");
+    
+    /* Core test case */
+    TCase *tc_core = tcase_create ("RemoteTests");
+    tcase_add_checked_fixture (tc_core, _setup, _teardown);
+    tcase_add_test (tc_core, test_pluginremote_create);
+    tcase_add_test (tc_core, test_pluginremote_plugind_create);
+    tcase_add_test (tc_core, test_pluginremote_plugind_kill);
+    tcase_add_test (tc_core, test_pluginremote_request);
+    tcase_add_test (tc_core, test_pluginremote_user_action_finished);
+    tcase_add_test (tc_core, test_pluginremote_refresh);
+    tcase_add_test (tc_core, test_plugind_daemon);
+    suite_add_tcase (s, tc_core);
+    return s;
+}
+
+int main (void)
+{
+    int number_failed;
+    
+    g_type_init();
+    
+    Suite *s = pluginremote_suite();
+    SRunner *sr = srunner_create(s);
+    srunner_run_all(sr, CK_NORMAL);
+    number_failed = srunner_ntests_failed(sr);
+    srunner_free(sr);
+    return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+  
index 585928a..4b0cc5b 100644 (file)
@@ -13,8 +13,8 @@ SUPPRESSIONS = $(top_srcdir)/test/valgrind.supp
        --error-exitcode=1 \
        ./$*
 
-valgrind: $(TESTS)
-       for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \
+valgrind: $(check_PROGRAMS)
+       for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(check_PROGRAMS)); do \
                $(MAKE) $$t.valgrind; \
        done;