diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2011-11-01 16:49:36 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2011-11-01 19:11:32 +0000 |
commit | 02925b6fb1e688819736a4f02ee06847748f0a07 (patch) | |
tree | 18bba65f9e26586939c8a2f935f1c5b310c9b0fc | |
parent | 71829b2af2282f96ec1887c361cdf66929836d7d (diff) |
GDBus tests: factor out TestIOStream, test_pipe and test_bidi_pipe
These might even make useful public API if they grew a Windows
implementation, but for now they can be Unix-only test API.
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=662395
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
-rw-r--r-- | gio/tests/Makefile.am | 10 | ||||
-rw-r--r-- | gio/tests/gdbus-non-socket.c | 143 | ||||
-rw-r--r-- | gio/tests/test-io-stream.c | 104 | ||||
-rw-r--r-- | gio/tests/test-io-stream.h | 53 | ||||
-rw-r--r-- | gio/tests/test-pipe-unix.c | 130 | ||||
-rw-r--r-- | gio/tests/test-pipe-unix.h | 37 |
6 files changed, 365 insertions, 112 deletions
diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am index 2493e4023..66fbd7139 100644 --- a/gio/tests/Makefile.am +++ b/gio/tests/Makefile.am @@ -332,7 +332,15 @@ gdbus_error_LDADD = $(progs_ldadd) gdbus_peer_SOURCES = gdbus-peer.c gdbus-tests.h gdbus-tests.c gdbus_peer_LDADD = $(progs_ldadd) -gdbus_non_socket_SOURCES = gdbus-non-socket.c gdbus-tests.h gdbus-tests.c +gdbus_non_socket_SOURCES = \ + gdbus-non-socket.c \ + gdbus-tests.c \ + gdbus-tests.h \ + test-io-stream.c \ + test-io-stream.h \ + test-pipe-unix.c \ + test-pipe-unix.h \ + $(NULL) gdbus_non_socket_LDADD = $(progs_ldadd) gdbus_exit_on_close_SOURCES = gdbus-exit-on-close.c gdbus-sessionbus.c gdbus-sessionbus.h gdbus-tests.h gdbus-tests.c diff --git a/gio/tests/gdbus-non-socket.c b/gio/tests/gdbus-non-socket.c index 87256cd58..fcf097e27 100644 --- a/gio/tests/gdbus-non-socket.c +++ b/gio/tests/gdbus-non-socket.c @@ -39,95 +39,8 @@ static GMainLoop *loop = NULL; /* ---------------------------------------------------------------------------------------------------- */ #ifdef G_OS_UNIX -#define MY_TYPE_IO_STREAM (my_io_stream_get_type ()) -#define MY_IO_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MY_TYPE_IO_STREAM, MyIOStream)) -#define MY_IS_IO_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MY_TYPE_IO_STREAM)) - -typedef struct -{ - GIOStream parent_instance; - GInputStream *input_stream; - GOutputStream *output_stream; -} MyIOStream; - -typedef struct -{ - GIOStreamClass parent_class; -} MyIOStreamClass; - -static GType my_io_stream_get_type (void) G_GNUC_CONST; - -G_DEFINE_TYPE (MyIOStream, my_io_stream, G_TYPE_IO_STREAM); - -static void -my_io_stream_finalize (GObject *object) -{ - MyIOStream *stream = MY_IO_STREAM (object); - g_object_unref (stream->input_stream); - g_object_unref (stream->output_stream); - G_OBJECT_CLASS (my_io_stream_parent_class)->finalize (object); -} - -static void -my_io_stream_init (MyIOStream *stream) -{ -} - -static GInputStream * -my_io_stream_get_input_stream (GIOStream *_stream) -{ - MyIOStream *stream = MY_IO_STREAM (_stream); - return stream->input_stream; -} - -static GOutputStream * -my_io_stream_get_output_stream (GIOStream *_stream) -{ - MyIOStream *stream = MY_IO_STREAM (_stream); - return stream->output_stream; -} - -static void -my_io_stream_class_init (MyIOStreamClass *klass) -{ - GObjectClass *gobject_class; - GIOStreamClass *giostream_class; - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = my_io_stream_finalize; - - giostream_class = G_IO_STREAM_CLASS (klass); - giostream_class->get_input_stream = my_io_stream_get_input_stream; - giostream_class->get_output_stream = my_io_stream_get_output_stream; -} - -static GIOStream * -my_io_stream_new (GInputStream *input_stream, - GOutputStream *output_stream) -{ - MyIOStream *stream; - g_return_val_if_fail (G_IS_INPUT_STREAM (input_stream), NULL); - g_return_val_if_fail (G_IS_OUTPUT_STREAM (output_stream), NULL); - stream = MY_IO_STREAM (g_object_new (MY_TYPE_IO_STREAM, NULL)); - stream->input_stream = g_object_ref (input_stream); - stream->output_stream = g_object_ref (output_stream); - return G_IO_STREAM (stream); -} - -static GIOStream * -my_io_stream_new_for_fds (gint fd_in, gint fd_out) -{ - GIOStream *stream; - GInputStream *input_stream; - GOutputStream *output_stream; - - input_stream = g_unix_input_stream_new (fd_in, TRUE); - output_stream = g_unix_output_stream_new (fd_out, TRUE); - stream = my_io_stream_new (input_stream, output_stream); - g_object_unref (input_stream); - g_object_unref (output_stream); - return stream; -} +#include "test-pipe-unix.h" +#include "test-io-stream.h" /* ---------------------------------------------------------------------------------------------------- */ @@ -217,20 +130,26 @@ static const GDBusInterfaceVTable pokee_vtable = { static void test_non_socket (void) { - gint in_pipes[2]; - gint out_pipes[2]; - GIOStream *stream; + GIOStream *streams[2]; GDBusConnection *connection; GError *error; gchar *guid; pid_t first_child; - gint read_fd; - gint write_fd; GVariant *ret; const gchar *str; + gboolean ok; - g_assert_cmpint (pipe (in_pipes), ==, 0); - g_assert_cmpint (pipe (out_pipes), ==, 0); + error = NULL; + + ok = test_bidi_pipe (&streams[0], &streams[1], &error); + g_assert_no_error (error); + g_assert (ok); + g_assert (G_IS_IO_STREAM (streams[0])); + g_assert (G_IS_INPUT_STREAM (g_io_stream_get_input_stream (streams[0]))); + g_assert (G_IS_OUTPUT_STREAM (g_io_stream_get_output_stream (streams[0]))); + g_assert (G_IS_IO_STREAM (streams[1])); + g_assert (G_IS_INPUT_STREAM (g_io_stream_get_input_stream (streams[1]))); + g_assert (G_IS_OUTPUT_STREAM (g_io_stream_get_output_stream (streams[1]))); switch ((first_child = fork ())) { @@ -246,11 +165,11 @@ test_non_socket (void) */ loop = g_main_loop_new (NULL, FALSE); - read_fd = in_pipes[0]; - write_fd = out_pipes[1]; - g_assert_cmpint (close ( in_pipes[1]), ==, 0); /* close unused write end */ - g_assert_cmpint (close (out_pipes[0]), ==, 0); /* close unused read end */ - stream = my_io_stream_new_for_fds (read_fd, write_fd); + ok = g_io_stream_close (streams[1], NULL, &error); + g_assert_no_error (error); + g_assert (ok); + g_object_unref (streams[1]); + guid = g_dbus_generate_guid (); error = NULL; /* We need to delay message processing to avoid the race @@ -263,7 +182,7 @@ test_non_socket (void) * though) so in rare cases the parent sends the message before * we (the first child) register the object */ - connection = g_dbus_connection_new_sync (stream, + connection = g_dbus_connection_new_sync (streams[0], guid, G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, @@ -272,7 +191,7 @@ test_non_socket (void) &error); g_free (guid); g_assert_no_error (error); - g_object_unref (stream); + g_object_unref (streams[0]); /* make sure we exit along with the parent */ g_dbus_connection_set_exit_on_close (connection, TRUE); @@ -303,6 +222,9 @@ test_non_socket (void) if (!g_test_trap_fork (0, 0)) { /* parent */ + g_object_unref (streams[0]); + g_object_unref (streams[1]); + g_test_trap_assert_passed (); g_assert_cmpint (kill (first_child, SIGTERM), ==, 0); return; @@ -315,20 +237,19 @@ test_non_socket (void) */ loop = g_main_loop_new (NULL, FALSE); - read_fd = out_pipes[0]; - write_fd = in_pipes[1]; - g_assert_cmpint (close (out_pipes[1]), ==, 0); /* close unused write end */ - g_assert_cmpint (close ( in_pipes[0]), ==, 0); /* close unused read end */ - stream = my_io_stream_new_for_fds (read_fd, write_fd); - error = NULL; - connection = g_dbus_connection_new_sync (stream, + ok = g_io_stream_close (streams[0], NULL, &error); + g_assert_no_error (error); + g_assert (ok); + g_object_unref (streams[0]); + + connection = g_dbus_connection_new_sync (streams[1], NULL, /* guid */ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL, /* GDBusAuthObserver */ NULL, &error); g_assert_no_error (error); - g_object_unref (stream); + g_object_unref (streams[1]); /* poke the first child */ error = NULL; diff --git a/gio/tests/test-io-stream.c b/gio/tests/test-io-stream.c new file mode 100644 index 000000000..3338a9d94 --- /dev/null +++ b/gio/tests/test-io-stream.c @@ -0,0 +1,104 @@ +/* Simple I/O stream. This is a utility class for tests, not a test. + * + * Copyright © 2008-2010 Red Hat, Inc. + * Copyright © 2011 Nokia Corporation + * + * 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 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., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + * Author: Simon McVittie <simon.mcvittie@collabora.co.uk> + */ + +#include <gio/gio.h> + +#include "test-io-stream.h" + +G_DEFINE_TYPE (TestIOStream, test_io_stream, G_TYPE_IO_STREAM) + +static void +test_io_stream_finalize (GObject *object) +{ + TestIOStream *stream = TEST_IO_STREAM (object); + + /* strictly speaking we should unref these in dispose, but + * g_io_stream_dispose() wants them to still exist + */ + g_clear_object (&stream->input_stream); + g_clear_object (&stream->output_stream); + + G_OBJECT_CLASS (test_io_stream_parent_class)->finalize (object); +} + +static void +test_io_stream_init (TestIOStream *stream) +{ +} + +static GInputStream * +test_io_stream_get_input_stream (GIOStream *_stream) +{ + TestIOStream *stream = TEST_IO_STREAM (_stream); + + return stream->input_stream; +} + +static GOutputStream * +test_io_stream_get_output_stream (GIOStream *_stream) +{ + TestIOStream *stream = TEST_IO_STREAM (_stream); + + return stream->output_stream; +} + +static void +test_io_stream_class_init (TestIOStreamClass *klass) +{ + GObjectClass *gobject_class; + GIOStreamClass *giostream_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = test_io_stream_finalize; + + giostream_class = G_IO_STREAM_CLASS (klass); + giostream_class->get_input_stream = test_io_stream_get_input_stream; + giostream_class->get_output_stream = test_io_stream_get_output_stream; +} + +/* + * test_io_stream_new: + * @input_stream: an input stream + * @output_stream: an output stream + * + * Return a simple #GIOStream binding together @input_stream and + * @output_stream. They have no additional semantics as a result of being + * part of this I/O stream: in particular, closing one does not close + * the other (although closing the #GIOStream will close both sub-streams). + * + * Returns: (transfer full): a new #GIOStream + */ +GIOStream * +test_io_stream_new (GInputStream *input_stream, + GOutputStream *output_stream) +{ + TestIOStream *stream; + + g_return_val_if_fail (G_IS_INPUT_STREAM (input_stream), NULL); + g_return_val_if_fail (G_IS_OUTPUT_STREAM (output_stream), NULL); + stream = TEST_IO_STREAM (g_object_new (TEST_TYPE_IO_STREAM, NULL)); + stream->input_stream = g_object_ref (input_stream); + stream->output_stream = g_object_ref (output_stream); + return G_IO_STREAM (stream); +} diff --git a/gio/tests/test-io-stream.h b/gio/tests/test-io-stream.h new file mode 100644 index 000000000..60feceb3b --- /dev/null +++ b/gio/tests/test-io-stream.h @@ -0,0 +1,53 @@ +/* Simple I/O stream. This is a utility module for tests, not a test. + * + * Copyright © 2008-2010 Red Hat, Inc. + * Copyright © 2011 Nokia Corporation + * + * 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 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., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + * Author: Simon McVittie <simon.mcvittie@collabora.co.uk> + */ + +#ifndef TEST_IO_STREAM_H +#define TEST_IO_STREAM_H + +#include <gio/gio.h> + +typedef struct +{ + GIOStream parent_instance; + GInputStream *input_stream; + GOutputStream *output_stream; +} TestIOStream; + +typedef struct +{ + GIOStreamClass parent_class; +} TestIOStreamClass; + +GType test_io_stream_get_type (void) G_GNUC_CONST; + +#define TEST_TYPE_IO_STREAM (test_io_stream_get_type ()) +#define TEST_IO_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + TEST_TYPE_IO_STREAM, TestIOStream)) +#define TEST_IS_IO_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + TEST_TYPE_IO_STREAM)) + +GIOStream *test_io_stream_new (GInputStream *input_stream, + GOutputStream *output_stream); + +#endif /* guard */ diff --git a/gio/tests/test-pipe-unix.c b/gio/tests/test-pipe-unix.c new file mode 100644 index 000000000..a3fdba4ab --- /dev/null +++ b/gio/tests/test-pipe-unix.c @@ -0,0 +1,130 @@ +/* Unix pipe-to-self. This is a utility module for tests, not a test. + * + * Copyright © 2008-2010 Red Hat, Inc. + * Copyright © 2011 Nokia Corporation + * + * 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 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., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Simon McVittie <simon.mcvittie@collabora.co.uk> + */ + +#include <errno.h> +#include <unistd.h> + +#include <gio/gio.h> + +#include "test-io-stream.h" + +#ifdef G_OS_UNIX +# include <gio/gunixinputstream.h> +# include <gio/gunixoutputstream.h> +#else +# error This module only exists on Unix +#endif + +/* + * test_pipe: + * @is: (out) (allow-none): used to return a #GInputStream + * @os: (out) (allow-none): used to return a #GOutputStream + * @error: used to raise an error + * + * Return a "pipe to self" connecting @is to @os. This can be used + * as a unidirectional pipe to or from a child process, for instance. + * + * See test_bidi_pipe() if you want to emulate a bidirectional pipe + * via a pair of unidirectional pipes. + * + * Returns: %TRUE on success + */ +gboolean +test_pipe (GInputStream **is, + GOutputStream **os, + GError **error) +{ + int pipefd[2]; + int ret; + + ret = pipe (pipefd); + + if (ret != 0) + { + int e = errno; + + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (e), + g_strerror (e)); + return FALSE; + } + + if (is != NULL) + *is = g_unix_input_stream_new (pipefd[0], TRUE); + else + close (pipefd[0]); + + if (os != NULL) + *os = g_unix_output_stream_new (pipefd[1], TRUE); + else + close (pipefd[1]); + + return TRUE; +} + +/* + * test_bidi_pipe: + * @left: (out) (allow-none): used to return one #GIOStream + * @right: (out) (allow-none): used to return the other #GIOStream + * @error: used to raise an error + * + * Return two #GIOStream<!---->s connected to each other with pipes. + * The "left" input stream is connected by a unidirectional pipe + * to the "right" output stream, and vice versa. This can be used + * as a bidirectional pipe to a child process, for instance. + * + * See test_pipe() if you only need a one-way pipe. + * + * Returns: %TRUE on success + */ +gboolean +test_bidi_pipe (GIOStream **left, + GIOStream **right, + GError **error) +{ + GInputStream *left_in = NULL; + GOutputStream *left_out = NULL; + GInputStream *right_in = NULL; + GOutputStream *right_out = NULL; + gboolean ret; + + if (!test_pipe (&left_in, &right_out, error)) + goto out; + + if (!test_pipe (&right_in, &left_out, error)) + goto out; + + if (left != NULL) + *left = test_io_stream_new (left_in, left_out); + + if (right != NULL) + *right = test_io_stream_new (right_in, right_out); + + ret = TRUE; + +out: + g_clear_object (&left_in); + g_clear_object (&left_out); + g_clear_object (&right_in); + g_clear_object (&right_out); + return ret; +} diff --git a/gio/tests/test-pipe-unix.h b/gio/tests/test-pipe-unix.h new file mode 100644 index 000000000..37a5a48da --- /dev/null +++ b/gio/tests/test-pipe-unix.h @@ -0,0 +1,37 @@ +/* Unix pipe-to-self. This is a utility module for tests, not a test. + * + * Copyright © 2008-2010 Red Hat, Inc. + * Copyright © 2011 Nokia Corporation + * + * 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 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., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Simon McVittie <simon.mcvittie@collabora.co.uk> + */ + +#ifndef TEST_PIPE_UNIX_H +#define TEST_PIPE_UNIX_H + +#include <gio/gio.h> + +gboolean test_pipe (GInputStream **is, + GOutputStream **os, + GError **error); + +gboolean test_bidi_pipe (GIOStream **left, + GIOStream **right, + GError **error); + +#endif /* guard */ |