mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-01 23:13:40 +02:00
Revert "Move gio tests from gio/tests/ to tests/gio/"
This reverts commit 2262d76b33
.
Move GIO tests back to where they belong.
This commit is contained in:
24
gio/tests/.gitignore
vendored
Normal file
24
gio/tests/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
buffered-input-stream
|
||||
desktop-app-info
|
||||
g-icon
|
||||
simple-async-result
|
||||
unix-streams
|
||||
data-input-stream
|
||||
data-output-stream
|
||||
g-file
|
||||
g-file-info
|
||||
live-g-file
|
||||
memory-input-stream
|
||||
memory-output-stream
|
||||
filter-streams
|
||||
sleepy-stream
|
||||
resolver
|
||||
connectable
|
||||
echo-server
|
||||
httpd
|
||||
readwrite
|
||||
send-data
|
||||
socket-client
|
||||
socket-server
|
||||
srvtarget
|
||||
contexts
|
119
gio/tests/Makefile.am
Normal file
119
gio/tests/Makefile.am
Normal file
@@ -0,0 +1,119 @@
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
INCLUDES = \
|
||||
-g \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/glib \
|
||||
-I$(top_srcdir)/gmodule \
|
||||
-I$(top_srcdir)/gobject \
|
||||
-I$(top_srcdir)/gio \
|
||||
$(GLIB_DEBUG_FLAGS) \
|
||||
-DSRCDIR=\""$(srcdir)"\"
|
||||
|
||||
noinst_PROGRAMS = $(TEST_PROGS) $(SAMPLE_PROGS)
|
||||
progs_ldadd = \
|
||||
$(top_builddir)/glib/libglib-2.0.la \
|
||||
$(top_builddir)/gobject/libgobject-2.0.la \
|
||||
$(top_builddir)/gio/libgio-2.0.la
|
||||
|
||||
|
||||
TEST_PROGS += \
|
||||
memory-input-stream \
|
||||
memory-output-stream \
|
||||
readwrite \
|
||||
g-file \
|
||||
g-file-info \
|
||||
data-input-stream \
|
||||
data-output-stream \
|
||||
g-icon \
|
||||
buffered-input-stream \
|
||||
sleepy-stream \
|
||||
filter-streams \
|
||||
simple-async-result \
|
||||
srvtarget \
|
||||
contexts
|
||||
|
||||
SAMPLE_PROGS = resolver socket-server socket-client echo-server httpd send-data
|
||||
|
||||
if OS_UNIX
|
||||
TEST_PROGS += live-g-file unix-streams desktop-app-info
|
||||
endif
|
||||
|
||||
memory_input_stream_SOURCES = memory-input-stream.c
|
||||
memory_input_stream_LDADD = $(progs_ldadd)
|
||||
|
||||
memory_output_stream_SOURCES = memory-output-stream.c
|
||||
memory_output_stream_LDADD = $(progs_ldadd)
|
||||
|
||||
g_file_SOURCES = g-file.c
|
||||
g_file_LDADD = $(progs_ldadd)
|
||||
|
||||
readwrite_SOURCES = readwrite.c
|
||||
readwrite_LDADD = $(progs_ldadd)
|
||||
|
||||
g_file_info_SOURCES = g-file-info.c
|
||||
g_file_info_LDADD = $(progs_ldadd)
|
||||
|
||||
data_input_stream_SOURCES = data-input-stream.c
|
||||
data_input_stream_LDADD = $(progs_ldadd)
|
||||
|
||||
data_output_stream_SOURCES = data-output-stream.c
|
||||
data_output_stream_LDADD = $(progs_ldadd)
|
||||
|
||||
g_icon_SOURCES = g-icon.c
|
||||
g_icon_LDADD = $(progs_ldadd)
|
||||
|
||||
buffered_input_stream_SOURCES = buffered-input-stream.c
|
||||
buffered_input_stream_LDADD = $(progs_ldadd)
|
||||
|
||||
live_g_file_SOURCES = live-g-file.c
|
||||
live_g_file_LDADD = $(progs_ldadd)
|
||||
|
||||
desktop_app_info_SOURCES = desktop-app-info.c
|
||||
desktop_app_info_LDADD = $(progs_ldadd)
|
||||
|
||||
unix_streams_SOURCES = unix-streams.c
|
||||
unix_streams_LDADD = $(progs_ldadd) \
|
||||
$(top_builddir)/gthread/libgthread-2.0.la
|
||||
|
||||
simple_async_result_SOURCES = simple-async-result.c
|
||||
simple_async_result_LDADD = $(progs_ldadd)
|
||||
|
||||
sleepy_stream_SOURCES = sleepy-stream.c
|
||||
sleepy_stream_LDADD = $(progs_ldadd)
|
||||
|
||||
filter_streams_SOURCES = filter-streams.c
|
||||
filter_streams_LDADD = $(progs_ldadd)
|
||||
|
||||
resolver_SOURCES = resolver.c
|
||||
resolver_LDADD = $(progs_ldadd) \
|
||||
$(top_builddir)/gthread/libgthread-2.0.la
|
||||
|
||||
socket_server_SOURCES = socket-server.c
|
||||
socket_server_LDADD = $(progs_ldadd) \
|
||||
$(top_builddir)/gthread/libgthread-2.0.la
|
||||
|
||||
socket_client_SOURCES = socket-client.c
|
||||
socket_client_LDADD = $(progs_ldadd) \
|
||||
$(top_builddir)/gthread/libgthread-2.0.la
|
||||
|
||||
echo_server_SOURCES = echo-server.c
|
||||
echo_server_LDADD = $(progs_ldadd) \
|
||||
$(top_builddir)/gthread/libgthread-2.0.la
|
||||
|
||||
httpd_SOURCES = httpd.c
|
||||
httpd_LDADD = $(progs_ldadd) \
|
||||
$(top_builddir)/gthread/libgthread-2.0.la
|
||||
|
||||
send_data_SOURCES = send-data.c
|
||||
send_data_LDADD = $(progs_ldadd) \
|
||||
$(top_builddir)/gthread/libgthread-2.0.la
|
||||
|
||||
srvtarget_SOURCES = srvtarget.c
|
||||
srvtarget_LDADD = $(progs_ldadd)
|
||||
|
||||
contexts_SOURCES = contexts.c
|
||||
contexts_LDADD = $(progs_ldadd) \
|
||||
$(top_builddir)/gthread/libgthread-2.0.la
|
||||
|
||||
DISTCLEAN_FILES = applications/mimeinfo.cache
|
60
gio/tests/buffered-input-stream.c
Normal file
60
gio/tests/buffered-input-stream.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Authors: Matthias Clasen <mclasen@redhat.com>
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
test_read_byte (void)
|
||||
{
|
||||
GInputStream *base;
|
||||
GInputStream *in;
|
||||
|
||||
g_test_bug ("562393");
|
||||
|
||||
base = g_memory_input_stream_new_from_data ("abcdefghijk", -1, NULL);
|
||||
in = g_buffered_input_stream_new (base);
|
||||
|
||||
g_assert_cmpint (g_buffered_input_stream_read_byte (G_BUFFERED_INPUT_STREAM (in), NULL, NULL), ==, 'a');
|
||||
g_assert_cmpint (g_buffered_input_stream_read_byte (G_BUFFERED_INPUT_STREAM (in), NULL, NULL), ==, 'b');
|
||||
g_assert_cmpint (g_buffered_input_stream_read_byte (G_BUFFERED_INPUT_STREAM (in), NULL, NULL), ==, 'c');
|
||||
|
||||
g_assert_cmpint (g_input_stream_skip (in, 3, NULL, NULL), ==, 3);
|
||||
|
||||
g_assert_cmpint (g_buffered_input_stream_read_byte (G_BUFFERED_INPUT_STREAM (in), NULL, NULL), ==, 'g');
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||
|
||||
g_test_add_func ("/buffered-input-stream/read-byte", test_read_byte);
|
||||
|
||||
return g_test_run();
|
||||
}
|
190
gio/tests/contexts.c
Normal file
190
gio/tests/contexts.c
Normal file
@@ -0,0 +1,190 @@
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEST_FILE (SRCDIR "/Makefile.am")
|
||||
char *test_file_buffer;
|
||||
gsize test_file_size;
|
||||
static char async_read_buffer[8192];
|
||||
|
||||
static void
|
||||
read_data (GObject *source, GAsyncResult *result, gpointer loop)
|
||||
{
|
||||
GInputStream *in = G_INPUT_STREAM (source);
|
||||
GError *error = NULL;
|
||||
gssize nread;
|
||||
|
||||
nread = g_input_stream_read_finish (in, result, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_cmpint (nread, >, 0);
|
||||
g_assert_cmpint (nread, <=, MIN(sizeof (async_read_buffer), test_file_size));
|
||||
g_assert (memcmp (async_read_buffer, test_file_buffer, nread) == 0);
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
opened_for_read (GObject *source, GAsyncResult *result, gpointer loop)
|
||||
{
|
||||
GFile *file = G_FILE (source);
|
||||
GFileInputStream *in;
|
||||
GError *error = NULL;
|
||||
|
||||
in = g_file_read_finish (file, result, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
memset (async_read_buffer, 0, sizeof (async_read_buffer));
|
||||
g_input_stream_read_async (G_INPUT_STREAM (in),
|
||||
async_read_buffer, sizeof (async_read_buffer),
|
||||
G_PRIORITY_DEFAULT, NULL,
|
||||
read_data, loop);
|
||||
}
|
||||
|
||||
/* Test 1: Async I/O started in a thread with a thread-default context
|
||||
* will stick to that thread, and will complete even if the default
|
||||
* main loop is blocked. (NB: the last part would not be true if we
|
||||
* were testing GFileMonitor!)
|
||||
*/
|
||||
|
||||
static gboolean idle_start_test1_thread (gpointer loop);
|
||||
static gpointer test1_thread (gpointer user_data);
|
||||
|
||||
static GCond *test1_cond;
|
||||
static GMutex *test1_mutex;
|
||||
|
||||
static void
|
||||
test_thread_independence (void)
|
||||
{
|
||||
GMainLoop *loop;
|
||||
|
||||
test1_cond = g_cond_new ();
|
||||
test1_mutex = g_mutex_new ();
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
g_idle_add (idle_start_test1_thread, loop);
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
|
||||
g_mutex_free (test1_mutex);
|
||||
g_cond_free (test1_cond);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_start_test1_thread (gpointer loop)
|
||||
{
|
||||
GTimeVal time;
|
||||
GThread *thread;
|
||||
gboolean io_completed;
|
||||
|
||||
g_mutex_lock (test1_mutex);
|
||||
thread = g_thread_create (test1_thread, NULL, TRUE, NULL);
|
||||
|
||||
g_get_current_time (&time);
|
||||
time.tv_sec += 2;
|
||||
io_completed = g_cond_timed_wait (test1_cond, test1_mutex, &time);
|
||||
g_assert (io_completed);
|
||||
g_thread_join (thread);
|
||||
|
||||
g_mutex_unlock (test1_mutex);
|
||||
g_main_loop_quit (loop);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
test1_thread (gpointer user_data)
|
||||
{
|
||||
GMainContext *context;
|
||||
GMainLoop *loop;
|
||||
GFile *file;
|
||||
|
||||
/* Wait for main thread to be waiting on test1_cond */
|
||||
g_mutex_lock (test1_mutex);
|
||||
g_mutex_unlock (test1_mutex);
|
||||
|
||||
context = g_main_context_new ();
|
||||
g_assert (g_main_context_get_thread_default () == NULL);
|
||||
g_main_context_push_thread_default (context);
|
||||
g_assert (g_main_context_get_thread_default () == context);
|
||||
|
||||
file = g_file_new_for_path (TEST_FILE);
|
||||
g_assert (g_file_supports_thread_contexts (file));
|
||||
|
||||
loop = g_main_loop_new (context, FALSE);
|
||||
g_file_read_async (file, G_PRIORITY_DEFAULT, NULL,
|
||||
opened_for_read, loop);
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
|
||||
g_cond_signal (test1_cond);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Test 2: If we push a thread-default context in the main thread, we
|
||||
* can run async ops in that context without running the default
|
||||
* context.
|
||||
*/
|
||||
|
||||
static gboolean test2_fail (gpointer user_data);
|
||||
|
||||
static void
|
||||
test_context_independence (void)
|
||||
{
|
||||
GMainContext *context;
|
||||
GMainLoop *loop;
|
||||
GFile *file;
|
||||
guint default_timeout;
|
||||
GSource *thread_default_timeout;
|
||||
|
||||
context = g_main_context_new ();
|
||||
g_assert (g_main_context_get_thread_default () == NULL);
|
||||
g_main_context_push_thread_default (context);
|
||||
g_assert (g_main_context_get_thread_default () == context);
|
||||
|
||||
file = g_file_new_for_path (TEST_FILE);
|
||||
g_assert (g_file_supports_thread_contexts (file));
|
||||
|
||||
/* Add a timeout to the main loop, to fail immediately if it gets run */
|
||||
default_timeout = g_timeout_add_full (G_PRIORITY_HIGH, 0,
|
||||
test2_fail, NULL, NULL);
|
||||
/* Add a timeout to the alternate loop, to fail if the I/O *doesn't* run */
|
||||
thread_default_timeout = g_timeout_source_new_seconds (2);
|
||||
g_source_set_callback (thread_default_timeout, test2_fail, NULL, NULL);
|
||||
g_source_attach (thread_default_timeout, context);
|
||||
|
||||
loop = g_main_loop_new (context, FALSE);
|
||||
g_file_read_async (file, G_PRIORITY_DEFAULT, NULL,
|
||||
opened_for_read, loop);
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
|
||||
g_source_remove (default_timeout);
|
||||
g_source_destroy (thread_default_timeout);
|
||||
g_source_unref (thread_default_timeout);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test2_fail (gpointer user_data)
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
g_thread_init (NULL);
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_file_get_contents (TEST_FILE, &test_file_buffer,
|
||||
&test_file_size, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_test_add_func ("/gio/contexts/thread-independence", test_thread_independence);
|
||||
g_test_add_func ("/gio/contexts/context-independence", test_context_independence);
|
||||
|
||||
return g_test_run();
|
||||
}
|
336
gio/tests/data-input-stream.c
Normal file
336
gio/tests/data-input-stream.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Authors: Tomas Bzatek <tbzatek@redhat.com>
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_LINES 0xFFF
|
||||
#define MAX_BYTES 0x10000
|
||||
|
||||
static void
|
||||
test_seek_to_start (GInputStream *stream)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean res = g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, &error);
|
||||
g_assert_cmpint (res, ==, TRUE);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_lines (GDataStreamNewlineType newline_type)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GInputStream *base_stream;
|
||||
GError *error = NULL;
|
||||
char *data;
|
||||
int line;
|
||||
const char* lines[MAX_LINES];
|
||||
const char* endl[4] = {"\n", "\r", "\r\n", "\n"};
|
||||
|
||||
/* prepare data */
|
||||
int i;
|
||||
for (i = 0; i < MAX_LINES; i++)
|
||||
lines[i] = "some_text";
|
||||
|
||||
base_stream = g_memory_input_stream_new ();
|
||||
g_assert (base_stream != NULL);
|
||||
stream = G_INPUT_STREAM (g_data_input_stream_new (base_stream));
|
||||
g_assert(stream != NULL);
|
||||
|
||||
/* Byte order testing */
|
||||
g_data_input_stream_set_byte_order (G_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
|
||||
g_assert_cmpint (g_data_input_stream_get_byte_order (G_DATA_INPUT_STREAM (stream)), ==, G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
|
||||
g_data_input_stream_set_byte_order (G_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
|
||||
g_assert_cmpint (g_data_input_stream_get_byte_order (G_DATA_INPUT_STREAM (stream)), ==, G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
|
||||
|
||||
/* Line ends testing */
|
||||
g_data_input_stream_set_newline_type (G_DATA_INPUT_STREAM (stream), newline_type);
|
||||
g_assert_cmpint (g_data_input_stream_get_newline_type (G_DATA_INPUT_STREAM (stream)), ==, newline_type);
|
||||
|
||||
|
||||
/* Add sample data */
|
||||
for (i = 0; i < MAX_LINES; i++)
|
||||
g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (base_stream),
|
||||
g_strconcat (lines[i], endl[newline_type], NULL), -1, NULL);
|
||||
|
||||
/* Seek to the start */
|
||||
test_seek_to_start (base_stream);
|
||||
|
||||
/* Test read line */
|
||||
error = NULL;
|
||||
data = (char*)1;
|
||||
line = 0;
|
||||
while (data)
|
||||
{
|
||||
gsize length = -1;
|
||||
data = g_data_input_stream_read_line (G_DATA_INPUT_STREAM (stream), &length, NULL, &error);
|
||||
if (data)
|
||||
{
|
||||
g_assert_cmpstr (data, ==, lines[line]);
|
||||
g_assert_no_error (error);
|
||||
line++;
|
||||
}
|
||||
}
|
||||
g_assert_cmpint (line, ==, MAX_LINES);
|
||||
|
||||
|
||||
g_object_unref (base_stream);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_lines_LF (void)
|
||||
{
|
||||
test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_LF);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_lines_CR (void)
|
||||
{
|
||||
test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_CR);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_lines_CR_LF (void)
|
||||
{
|
||||
test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_CR_LF);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_read_until (void)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GInputStream *base_stream;
|
||||
GError *error = NULL;
|
||||
char *data;
|
||||
int line;
|
||||
int i;
|
||||
|
||||
#define REPEATS 10 /* number of rounds */
|
||||
#define DATA_STRING " part1 # part2 $ part3 % part4 ^"
|
||||
#define DATA_PART_LEN 7 /* number of characters between separators */
|
||||
#define DATA_SEP "#$%^"
|
||||
const int DATA_PARTS_NUM = strlen (DATA_SEP) * REPEATS;
|
||||
|
||||
base_stream = g_memory_input_stream_new ();
|
||||
stream = G_INPUT_STREAM (g_data_input_stream_new (base_stream));
|
||||
|
||||
for (i = 0; i < REPEATS; i++)
|
||||
g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (base_stream), DATA_STRING, -1, NULL);
|
||||
|
||||
/* Test stop characters */
|
||||
error = NULL;
|
||||
data = (char*)1;
|
||||
line = 0;
|
||||
while (data)
|
||||
{
|
||||
gsize length = -1;
|
||||
data = g_data_input_stream_read_until (G_DATA_INPUT_STREAM (stream), DATA_SEP, &length, NULL, &error);
|
||||
if (data)
|
||||
{
|
||||
g_assert_cmpint (strlen (data), ==, DATA_PART_LEN);
|
||||
g_assert_no_error (error);
|
||||
line++;
|
||||
}
|
||||
}
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpint (line, ==, DATA_PARTS_NUM);
|
||||
|
||||
|
||||
g_object_unref (base_stream);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
enum TestDataType {
|
||||
TEST_DATA_BYTE = 0,
|
||||
TEST_DATA_INT16,
|
||||
TEST_DATA_UINT16,
|
||||
TEST_DATA_INT32,
|
||||
TEST_DATA_UINT32,
|
||||
TEST_DATA_INT64,
|
||||
TEST_DATA_UINT64
|
||||
};
|
||||
|
||||
#define TEST_DATA_RETYPE_BUFF(a, t, v) \
|
||||
(a == TEST_DATA_BYTE ? (t) *(guchar*)v : \
|
||||
(a == TEST_DATA_INT16 ? (t) *(gint16*)v : \
|
||||
(a == TEST_DATA_UINT16 ? (t) *(guint16*)v : \
|
||||
(a == TEST_DATA_INT32 ? (t) *(gint32*)v : \
|
||||
(a == TEST_DATA_UINT32 ? (t) *(guint32*)v : \
|
||||
(a == TEST_DATA_INT64 ? (t) *(gint64*)v : \
|
||||
(t) *(guint64*)v ))))))
|
||||
|
||||
|
||||
static void
|
||||
test_data_array (GInputStream *stream, GInputStream *base_stream,
|
||||
gpointer buffer, int len,
|
||||
enum TestDataType data_type, GDataStreamByteOrder byte_order)
|
||||
{
|
||||
GError *error = NULL;
|
||||
int pos = 0;
|
||||
int data_size = 1;
|
||||
gint64 data;
|
||||
GDataStreamByteOrder native;
|
||||
gboolean swap;
|
||||
|
||||
/* Seek to start */
|
||||
test_seek_to_start (base_stream);
|
||||
|
||||
/* Set correct data size */
|
||||
switch (data_type)
|
||||
{
|
||||
case TEST_DATA_BYTE:
|
||||
data_size = 1;
|
||||
break;
|
||||
case TEST_DATA_INT16:
|
||||
case TEST_DATA_UINT16:
|
||||
data_size = 2;
|
||||
break;
|
||||
case TEST_DATA_INT32:
|
||||
case TEST_DATA_UINT32:
|
||||
data_size = 4;
|
||||
break;
|
||||
case TEST_DATA_INT64:
|
||||
case TEST_DATA_UINT64:
|
||||
data_size = 8;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set flag to swap bytes if needed */
|
||||
native = (G_BYTE_ORDER == G_BIG_ENDIAN) ? G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN : G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
|
||||
swap = (byte_order != G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN) && (byte_order != native);
|
||||
|
||||
data = 1;
|
||||
while (data != 0)
|
||||
{
|
||||
switch (data_type)
|
||||
{
|
||||
case TEST_DATA_BYTE:
|
||||
data = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (stream), NULL, &error);
|
||||
break;
|
||||
case TEST_DATA_INT16:
|
||||
data = g_data_input_stream_read_int16 (G_DATA_INPUT_STREAM (stream), NULL, &error);
|
||||
if (swap)
|
||||
data = (gint16)GUINT16_SWAP_LE_BE((gint16)data);
|
||||
break;
|
||||
case TEST_DATA_UINT16:
|
||||
data = g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (stream), NULL, &error);
|
||||
if (swap)
|
||||
data = (guint16)GUINT16_SWAP_LE_BE((guint16)data);
|
||||
break;
|
||||
case TEST_DATA_INT32:
|
||||
data = g_data_input_stream_read_int32 (G_DATA_INPUT_STREAM (stream), NULL, &error);
|
||||
if (swap)
|
||||
data = (gint32)GUINT32_SWAP_LE_BE((gint32)data);
|
||||
break;
|
||||
case TEST_DATA_UINT32:
|
||||
data = g_data_input_stream_read_uint32 (G_DATA_INPUT_STREAM (stream), NULL, &error);
|
||||
if (swap)
|
||||
data = (guint32)GUINT32_SWAP_LE_BE((guint32)data);
|
||||
break;
|
||||
case TEST_DATA_INT64:
|
||||
data = g_data_input_stream_read_int64 (G_DATA_INPUT_STREAM (stream), NULL, &error);
|
||||
if (swap)
|
||||
data = (gint64)GUINT64_SWAP_LE_BE((gint64)data);
|
||||
break;
|
||||
case TEST_DATA_UINT64:
|
||||
data = g_data_input_stream_read_uint64 (G_DATA_INPUT_STREAM (stream), NULL, &error);
|
||||
if (swap)
|
||||
data = (guint64)GUINT64_SWAP_LE_BE((guint64)data);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
if ((data) && (! error))
|
||||
g_assert_cmpint (data, ==, TEST_DATA_RETYPE_BUFF(data_type, gint64, ((guchar*)buffer + pos)));
|
||||
|
||||
pos += data_size;
|
||||
}
|
||||
if (pos < len + 1)
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpint (pos - data_size, ==, len);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_int (void)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GInputStream *base_stream;
|
||||
GRand *randomizer;
|
||||
int i;
|
||||
gpointer buffer;
|
||||
|
||||
randomizer = g_rand_new ();
|
||||
buffer = g_malloc0 (MAX_BYTES);
|
||||
|
||||
/* Fill in some random data */
|
||||
for (i = 0; i < MAX_BYTES; i++)
|
||||
{
|
||||
guchar x = 0;
|
||||
while (! x)
|
||||
x = (guchar)g_rand_int (randomizer);
|
||||
*(guchar*)((guchar*)buffer + sizeof(guchar) * i) = x;
|
||||
}
|
||||
|
||||
base_stream = g_memory_input_stream_new ();
|
||||
stream = G_INPUT_STREAM (g_data_input_stream_new (base_stream));
|
||||
g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (base_stream), buffer, MAX_BYTES, NULL);
|
||||
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
int j;
|
||||
g_data_input_stream_set_byte_order (G_DATA_INPUT_STREAM (stream), i);
|
||||
|
||||
for (j = 0; j <= TEST_DATA_UINT64; j++)
|
||||
test_data_array (stream, base_stream, buffer, MAX_BYTES, j, i);
|
||||
}
|
||||
|
||||
g_object_unref (base_stream);
|
||||
g_object_unref (stream);
|
||||
g_rand_free (randomizer);
|
||||
g_free (buffer);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/data-input-stream/read-lines-LF", test_read_lines_LF);
|
||||
g_test_add_func ("/data-input-stream/read-lines-CR", test_read_lines_CR);
|
||||
g_test_add_func ("/data-input-stream/read-lines-CR-LF", test_read_lines_CR_LF);
|
||||
g_test_add_func ("/data-input-stream/read-until", test_read_until);
|
||||
g_test_add_func ("/data-input-stream/read-int", test_read_int);
|
||||
|
||||
return g_test_run();
|
||||
}
|
289
gio/tests/data-output-stream.c
Normal file
289
gio/tests/data-output-stream.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Authors: Tomas Bzatek <tbzatek@redhat.com>
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_LINES 0xFFF
|
||||
#define MAX_LINES_BUFF 0xFFFFFF
|
||||
#define MAX_BYTES_BINARY 0x100
|
||||
|
||||
static void
|
||||
test_read_lines (GDataStreamNewlineType newline_type)
|
||||
{
|
||||
GOutputStream *stream;
|
||||
GOutputStream *base_stream;
|
||||
GError *error = NULL;
|
||||
gpointer data;
|
||||
char *lines;
|
||||
int size;
|
||||
int i;
|
||||
|
||||
#define TEST_STRING "some_text"
|
||||
|
||||
const char* endl[4] = {"\n", "\r", "\r\n", "\n"};
|
||||
|
||||
|
||||
data = g_malloc0 (MAX_LINES_BUFF);
|
||||
lines = g_malloc0 ((strlen (TEST_STRING) + strlen (endl[newline_type])) * MAX_LINES + 1);
|
||||
|
||||
/* initialize objects */
|
||||
base_stream = g_memory_output_stream_new (data, MAX_LINES_BUFF, NULL, NULL);
|
||||
stream = G_OUTPUT_STREAM (g_data_output_stream_new (base_stream));
|
||||
|
||||
|
||||
/* fill data */
|
||||
for (i = 0; i < MAX_LINES; i++)
|
||||
{
|
||||
gboolean res;
|
||||
char *s = g_strconcat (TEST_STRING, endl[newline_type], NULL);
|
||||
res = g_data_output_stream_put_string (G_DATA_OUTPUT_STREAM (stream), s, NULL, &error);
|
||||
g_stpcpy ((char*)(lines + i*strlen(s)), s);
|
||||
g_assert_no_error (error);
|
||||
g_assert (res == TRUE);
|
||||
}
|
||||
|
||||
/* Byte order testing */
|
||||
g_data_output_stream_set_byte_order (G_DATA_OUTPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
|
||||
g_assert_cmpint (g_data_output_stream_get_byte_order (G_DATA_OUTPUT_STREAM (stream)), ==, G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
|
||||
g_data_output_stream_set_byte_order (G_DATA_OUTPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
|
||||
g_assert_cmpint (g_data_output_stream_get_byte_order (G_DATA_OUTPUT_STREAM (stream)), ==, G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
|
||||
|
||||
/* compare data */
|
||||
size = strlen (data);
|
||||
g_assert_cmpint (size, <, MAX_LINES_BUFF);
|
||||
g_assert_cmpstr ((char*)data, ==, lines);
|
||||
|
||||
g_object_unref (base_stream);
|
||||
g_object_unref (stream);
|
||||
g_free (data);
|
||||
g_free (lines);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_lines_LF (void)
|
||||
{
|
||||
test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_LF);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_lines_CR (void)
|
||||
{
|
||||
test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_CR);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_lines_CR_LF (void)
|
||||
{
|
||||
test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_CR_LF);
|
||||
}
|
||||
|
||||
enum TestDataType {
|
||||
TEST_DATA_BYTE = 0,
|
||||
TEST_DATA_INT16,
|
||||
TEST_DATA_UINT16,
|
||||
TEST_DATA_INT32,
|
||||
TEST_DATA_UINT32,
|
||||
TEST_DATA_INT64,
|
||||
TEST_DATA_UINT64
|
||||
};
|
||||
|
||||
static void
|
||||
test_data_array (guchar *buffer, gsize len,
|
||||
enum TestDataType data_type, GDataStreamByteOrder byte_order)
|
||||
{
|
||||
GOutputStream *stream;
|
||||
GOutputStream *base_stream;
|
||||
guchar *stream_data;
|
||||
|
||||
GError *error = NULL;
|
||||
guint pos;
|
||||
GDataStreamByteOrder native;
|
||||
gboolean swap;
|
||||
gboolean res;
|
||||
|
||||
/* create objects */
|
||||
stream_data = g_malloc0 (len);
|
||||
base_stream = g_memory_output_stream_new (stream_data, len, NULL, NULL);
|
||||
stream = G_OUTPUT_STREAM (g_data_output_stream_new (base_stream));
|
||||
g_data_output_stream_set_byte_order (G_DATA_OUTPUT_STREAM (stream), byte_order);
|
||||
|
||||
/* Set flag to swap bytes if needed */
|
||||
native = (G_BYTE_ORDER == G_BIG_ENDIAN) ? G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN : G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
|
||||
swap = (byte_order != G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN) && (byte_order != native);
|
||||
|
||||
/* set len to length of buffer cast to actual type */
|
||||
switch (data_type)
|
||||
{
|
||||
case TEST_DATA_BYTE:
|
||||
break;
|
||||
case TEST_DATA_INT16:
|
||||
case TEST_DATA_UINT16:
|
||||
g_assert_cmpint (len % 2, ==, 0);
|
||||
case TEST_DATA_INT32:
|
||||
case TEST_DATA_UINT32:
|
||||
g_assert_cmpint (len % 4, ==, 0);
|
||||
case TEST_DATA_INT64:
|
||||
case TEST_DATA_UINT64:
|
||||
g_assert_cmpint (len % 8, ==, 0);
|
||||
len /= 8;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write data to the file */
|
||||
for (pos = 0; pos < len; pos++)
|
||||
{
|
||||
switch (data_type)
|
||||
{
|
||||
case TEST_DATA_BYTE:
|
||||
res = g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (stream), buffer[pos], NULL, &error);
|
||||
break;
|
||||
case TEST_DATA_INT16:
|
||||
res = g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (stream), ((gint16 *) buffer)[pos], NULL, &error);
|
||||
break;
|
||||
case TEST_DATA_UINT16:
|
||||
res = g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (stream), ((guint16 *) buffer)[pos], NULL, &error);
|
||||
break;
|
||||
case TEST_DATA_INT32:
|
||||
res = g_data_output_stream_put_int32 (G_DATA_OUTPUT_STREAM (stream), ((gint32 *) buffer)[pos], NULL, &error);
|
||||
break;
|
||||
case TEST_DATA_UINT32:
|
||||
res = g_data_output_stream_put_uint32 (G_DATA_OUTPUT_STREAM (stream), ((guint32 *) buffer)[pos], NULL, &error);
|
||||
break;
|
||||
case TEST_DATA_INT64:
|
||||
res = g_data_output_stream_put_int64 (G_DATA_OUTPUT_STREAM (stream), ((gint64 *) buffer)[pos], NULL, &error);
|
||||
break;
|
||||
case TEST_DATA_UINT64:
|
||||
res = g_data_output_stream_put_uint64 (G_DATA_OUTPUT_STREAM (stream), ((guint64 *) buffer)[pos], NULL, &error);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpint (res, ==, TRUE);
|
||||
}
|
||||
|
||||
/* Compare data back */
|
||||
for (pos = 0; pos < len; pos++)
|
||||
{
|
||||
switch (data_type)
|
||||
{
|
||||
case TEST_DATA_BYTE:
|
||||
/* swapping unnecessary */
|
||||
g_assert_cmpint (buffer[pos], ==, stream_data[pos]);
|
||||
break;
|
||||
case TEST_DATA_UINT16:
|
||||
if (swap)
|
||||
g_assert_cmpint (GUINT16_SWAP_LE_BE (((guint16 *) buffer)[pos]), ==, ((guint16 *) stream_data)[pos]);
|
||||
else
|
||||
g_assert_cmpint (((guint16 *) buffer)[pos], ==, ((guint16 *) stream_data)[pos]);
|
||||
break;
|
||||
case TEST_DATA_INT16:
|
||||
if (swap)
|
||||
g_assert_cmpint ((gint16) GUINT16_SWAP_LE_BE (((gint16 *) buffer)[pos]), ==, ((gint16 *) stream_data)[pos]);
|
||||
else
|
||||
g_assert_cmpint (((gint16 *) buffer)[pos], ==, ((gint16 *) stream_data)[pos]);
|
||||
break;
|
||||
case TEST_DATA_UINT32:
|
||||
if (swap)
|
||||
g_assert_cmpint (GUINT32_SWAP_LE_BE (((guint32 *) buffer)[pos]), ==, ((guint32 *) stream_data)[pos]);
|
||||
else
|
||||
g_assert_cmpint (((guint32 *) buffer)[pos], ==, ((guint32 *) stream_data)[pos]);
|
||||
break;
|
||||
case TEST_DATA_INT32:
|
||||
if (swap)
|
||||
g_assert_cmpint ((gint32) GUINT32_SWAP_LE_BE (((gint32 *) buffer)[pos]), ==, ((gint32 *) stream_data)[pos]);
|
||||
else
|
||||
g_assert_cmpint (((gint32 *) buffer)[pos], ==, ((gint32 *) stream_data)[pos]);
|
||||
break;
|
||||
case TEST_DATA_UINT64:
|
||||
if (swap)
|
||||
g_assert_cmpint (GUINT64_SWAP_LE_BE (((guint64 *) buffer)[pos]), ==, ((guint64 *) stream_data)[pos]);
|
||||
else
|
||||
g_assert_cmpint (((guint64 *) buffer)[pos], ==, ((guint64 *) stream_data)[pos]);
|
||||
break;
|
||||
case TEST_DATA_INT64:
|
||||
if (swap)
|
||||
g_assert_cmpint ((gint64) GUINT64_SWAP_LE_BE (((gint64 *) buffer)[pos]), ==, ((gint64 *) stream_data)[pos]);
|
||||
else
|
||||
g_assert_cmpint (((gint64 *) buffer)[pos], ==, ((gint64 *) stream_data)[pos]);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (base_stream);
|
||||
g_object_unref (stream);
|
||||
g_free (stream_data);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_int (void)
|
||||
{
|
||||
GRand *randomizer;
|
||||
gpointer buffer;
|
||||
int i;
|
||||
|
||||
randomizer = g_rand_new ();
|
||||
buffer = g_malloc0(MAX_BYTES_BINARY);
|
||||
|
||||
/* Fill in some random data */
|
||||
for (i = 0; i < MAX_BYTES_BINARY; i++)
|
||||
{
|
||||
guchar x = 0;
|
||||
while (! x) x = (guchar)g_rand_int (randomizer);
|
||||
*(guchar*)((guchar*)buffer + sizeof (guchar) * i) = x;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j <= TEST_DATA_UINT64; j++)
|
||||
test_data_array (buffer, MAX_BYTES_BINARY, j, i);
|
||||
}
|
||||
|
||||
g_rand_free (randomizer);
|
||||
g_free (buffer);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/data-input-stream/read-lines-LF", test_read_lines_LF);
|
||||
g_test_add_func ("/data-input-stream/read-lines-CR", test_read_lines_CR);
|
||||
g_test_add_func ("/data-input-stream/read-lines-CR-LF", test_read_lines_CR_LF);
|
||||
g_test_add_func ("/data-input-stream/read-int", test_read_int);
|
||||
|
||||
return g_test_run();
|
||||
}
|
259
gio/tests/desktop-app-info.c
Normal file
259
gio/tests/desktop-app-info.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Red Hat, Inc
|
||||
*
|
||||
* 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: Matthias Clasen
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gdesktopappinfo.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *basedir;
|
||||
|
||||
static GAppInfo *
|
||||
create_app_info (const char *name)
|
||||
{
|
||||
GError *error;
|
||||
GAppInfo *info;
|
||||
|
||||
error = NULL;
|
||||
info = g_app_info_create_from_commandline ("/usr/bin/true blah",
|
||||
name,
|
||||
G_APP_INFO_CREATE_NONE,
|
||||
&error);
|
||||
g_assert (error == NULL);
|
||||
|
||||
/* this is necessary to ensure that the info is saved */
|
||||
g_app_info_set_as_default_for_type (info, "application/x-blah", &error);
|
||||
g_assert (error == NULL);
|
||||
g_app_info_remove_supports_type (info, "application/x-blah", &error);
|
||||
g_assert (error == NULL);
|
||||
g_app_info_reset_type_associations ("application/x-blah");
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
test_delete (void)
|
||||
{
|
||||
GAppInfo *info;
|
||||
|
||||
const char *id;
|
||||
char *filename;
|
||||
gboolean res;
|
||||
|
||||
info = create_app_info ("Blah");
|
||||
|
||||
id = g_app_info_get_id (info);
|
||||
g_assert (id != NULL);
|
||||
|
||||
filename = g_build_filename (basedir, "applications", id, NULL);
|
||||
|
||||
res = g_file_test (filename, G_FILE_TEST_EXISTS);
|
||||
g_assert (res);
|
||||
|
||||
res = g_app_info_can_delete (info);
|
||||
g_assert (res);
|
||||
|
||||
res = g_app_info_delete (info);
|
||||
g_assert (res);
|
||||
|
||||
res = g_file_test (filename, G_FILE_TEST_EXISTS);
|
||||
g_assert (!res);
|
||||
|
||||
g_object_unref (info);
|
||||
|
||||
if (g_file_test ("/usr/share/applications/gedit.desktop", G_FILE_TEST_EXISTS))
|
||||
{
|
||||
info = (GAppInfo*)g_desktop_app_info_new ("gedit.desktop");
|
||||
g_assert (info);
|
||||
|
||||
res = g_app_info_can_delete (info);
|
||||
g_assert (!res);
|
||||
|
||||
res = g_app_info_delete (info);
|
||||
g_assert (!res);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_default (void)
|
||||
{
|
||||
GAppInfo *info, *info1, *info2, *info3;
|
||||
GList *list;
|
||||
GError *error = NULL;
|
||||
|
||||
info1 = create_app_info ("Blah1");
|
||||
info2 = create_app_info ("Blah2");
|
||||
info3 = create_app_info ("Blah3");
|
||||
|
||||
g_app_info_set_as_default_for_type (info1, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
|
||||
g_app_info_set_as_default_for_type (info2, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
|
||||
list = g_app_info_get_all_for_type ("application/x-test");
|
||||
g_assert (g_list_length (list) == 2);
|
||||
|
||||
/* check that both are in the list, info2 before info1 */
|
||||
info = (GAppInfo *)list->data;
|
||||
g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info2)) == 0);
|
||||
|
||||
info = (GAppInfo *)list->next->data;
|
||||
g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info1)) == 0);
|
||||
|
||||
g_list_foreach (list, (GFunc)g_object_unref, NULL);
|
||||
g_list_free (list);
|
||||
|
||||
/* now try adding something at the end */
|
||||
g_app_info_add_supports_type (info3, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
|
||||
list = g_app_info_get_all_for_type ("application/x-test");
|
||||
g_assert (g_list_length (list) == 3);
|
||||
|
||||
/* check that all are in the list, info2, info1, info3 */
|
||||
info = (GAppInfo *)list->data;
|
||||
g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info2)) == 0);
|
||||
|
||||
info = (GAppInfo *)list->next->data;
|
||||
g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info1)) == 0);
|
||||
|
||||
info = (GAppInfo *)list->next->next->data;
|
||||
g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info3)) == 0);
|
||||
|
||||
g_list_foreach (list, (GFunc)g_object_unref, NULL);
|
||||
g_list_free (list);
|
||||
|
||||
/* now remove info1 again */
|
||||
g_app_info_remove_supports_type (info1, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
|
||||
list = g_app_info_get_all_for_type ("application/x-test");
|
||||
g_assert (g_list_length (list) == 2);
|
||||
|
||||
/* check that both are in the list, info2 before info3 */
|
||||
info = (GAppInfo *)list->data;
|
||||
g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info2)) == 0);
|
||||
|
||||
info = (GAppInfo *)list->next->data;
|
||||
g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info3)) == 0);
|
||||
|
||||
g_list_foreach (list, (GFunc)g_object_unref, NULL);
|
||||
g_list_free (list);
|
||||
|
||||
/* now clean it all up */
|
||||
g_app_info_reset_type_associations ("application/x-test");
|
||||
|
||||
list = g_app_info_get_all_for_type ("application/x-test");
|
||||
g_assert (list == NULL);
|
||||
|
||||
g_app_info_delete (info1);
|
||||
g_app_info_delete (info2);
|
||||
g_app_info_delete (info3);
|
||||
|
||||
g_object_unref (info1);
|
||||
g_object_unref (info2);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_dir_recurse (GFile *parent, GFile *root)
|
||||
{
|
||||
gboolean res;
|
||||
GError *error;
|
||||
GFileEnumerator *enumerator;
|
||||
GFileInfo *info;
|
||||
GFile *descend;
|
||||
char *relative_path;
|
||||
|
||||
g_assert (root != NULL);
|
||||
|
||||
error = NULL;
|
||||
enumerator =
|
||||
g_file_enumerate_children (parent, "*",
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
|
||||
&error);
|
||||
if (! enumerator)
|
||||
return;
|
||||
error = NULL;
|
||||
info = g_file_enumerator_next_file (enumerator, NULL, &error);
|
||||
while ((info) && (!error))
|
||||
{
|
||||
descend = g_file_get_child (parent, g_file_info_get_name (info));
|
||||
g_assert (descend != NULL);
|
||||
relative_path = g_file_get_relative_path (root, descend);
|
||||
g_assert (relative_path != NULL);
|
||||
|
||||
if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
|
||||
cleanup_dir_recurse (descend, root);
|
||||
|
||||
error = NULL;
|
||||
res = g_file_delete (descend, NULL, &error);
|
||||
g_assert_cmpint (res, ==, TRUE);
|
||||
|
||||
g_object_unref (descend);
|
||||
error = NULL;
|
||||
info = g_file_enumerator_next_file (enumerator, NULL, &error);
|
||||
}
|
||||
g_assert (error == NULL);
|
||||
|
||||
error = NULL;
|
||||
res = g_file_enumerator_close (enumerator, NULL, &error);
|
||||
g_assert_cmpint (res, ==, TRUE);
|
||||
g_assert (error == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_subdirs (const char *base_dir)
|
||||
{
|
||||
GFile *base, *file;
|
||||
|
||||
base = g_file_new_for_path (base_dir);
|
||||
file = g_file_get_child (base, "applications");
|
||||
cleanup_dir_recurse (file, file);
|
||||
g_object_unref (file);
|
||||
file = g_file_get_child (base, "mime");
|
||||
cleanup_dir_recurse (file, file);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
gint result;
|
||||
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
basedir = g_get_current_dir ();
|
||||
g_setenv ("XDG_DATA_HOME", basedir, TRUE);
|
||||
cleanup_subdirs (basedir);
|
||||
|
||||
g_test_add_func ("/desktop-app-info/delete", test_delete);
|
||||
g_test_add_func ("/desktop-app-info/default", test_default);
|
||||
|
||||
result = g_test_run ();
|
||||
|
||||
cleanup_subdirs (basedir);
|
||||
|
||||
return result;
|
||||
}
|
73
gio/tests/echo-server.c
Normal file
73
gio/tests/echo-server.c
Normal file
@@ -0,0 +1,73 @@
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MESSAGE "Welcome to the echo service!\n"
|
||||
|
||||
int port = 7777;
|
||||
static GOptionEntry cmd_entries[] = {
|
||||
{"port", 'p', 0, G_OPTION_ARG_INT, &port,
|
||||
"Local port to bind to", NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
handler (GThreadedSocketService *service,
|
||||
GSocketConnection *connection,
|
||||
GSocketListener *listener,
|
||||
gpointer user_data)
|
||||
{
|
||||
GOutputStream *out;
|
||||
GInputStream *in;
|
||||
char buffer[1024];
|
||||
gssize size;
|
||||
|
||||
out = g_io_stream_get_output_stream (G_IO_STREAM (connection));
|
||||
in = g_io_stream_get_input_stream (G_IO_STREAM (connection));
|
||||
|
||||
g_output_stream_write_all (out, MESSAGE, strlen (MESSAGE),
|
||||
NULL, NULL, NULL);
|
||||
|
||||
while (0 < (size = g_input_stream_read (in, buffer,
|
||||
sizeof buffer, NULL, NULL)))
|
||||
g_output_stream_write (out, buffer, size, NULL, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GSocketService *service;
|
||||
GOptionContext *context;
|
||||
GError *error = NULL;
|
||||
|
||||
g_type_init ();
|
||||
g_thread_init (NULL);
|
||||
|
||||
context = g_option_context_new (" - Test GSocket server stuff");
|
||||
g_option_context_add_main_entries (context, cmd_entries, NULL);
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error))
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
service = g_threaded_socket_service_new (10);
|
||||
|
||||
if (!g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service),
|
||||
port,
|
||||
NULL,
|
||||
&error))
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_print ("Echo service listening on port %d\n", port);
|
||||
|
||||
g_signal_connect (service, "run", G_CALLBACK (handler), NULL);
|
||||
|
||||
g_main_loop_run (g_main_loop_new (NULL, FALSE));
|
||||
g_assert_not_reached ();
|
||||
}
|
239
gio/tests/filter-streams.c
Normal file
239
gio/tests/filter-streams.c
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright © 2009 Codethink Limited
|
||||
*
|
||||
* This program 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 licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* See the included COPYING file for more information.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
static void
|
||||
test_input_filter (void)
|
||||
{
|
||||
GInputStream *base, *f1, *f2;
|
||||
|
||||
g_test_bug ("568394");
|
||||
base = g_memory_input_stream_new_from_data ("abcdefghijk", -1, NULL);
|
||||
f1 = g_buffered_input_stream_new (base);
|
||||
f2 = g_buffered_input_stream_new (base);
|
||||
|
||||
g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (f1), FALSE);
|
||||
|
||||
g_assert (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (f1)) == base);
|
||||
g_assert (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (f2)) == base);
|
||||
|
||||
g_assert (!g_input_stream_is_closed (base));
|
||||
g_assert (!g_input_stream_is_closed (f1));
|
||||
g_assert (!g_input_stream_is_closed (f2));
|
||||
|
||||
g_object_unref (f1);
|
||||
|
||||
g_assert (!g_input_stream_is_closed (base));
|
||||
g_assert (!g_input_stream_is_closed (f2));
|
||||
|
||||
g_object_unref (f2);
|
||||
|
||||
g_assert (g_input_stream_is_closed (base));
|
||||
|
||||
g_object_unref (base);
|
||||
}
|
||||
|
||||
static void
|
||||
test_output_filter (void)
|
||||
{
|
||||
GOutputStream *base, *f1, *f2;
|
||||
|
||||
base = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||
f1 = g_buffered_output_stream_new (base);
|
||||
f2 = g_buffered_output_stream_new (base);
|
||||
|
||||
g_filter_output_stream_set_close_base_stream (G_FILTER_OUTPUT_STREAM (f1), FALSE);
|
||||
|
||||
g_assert (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (f1)) == base);
|
||||
g_assert (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (f2)) == base);
|
||||
|
||||
g_assert (!g_output_stream_is_closed (base));
|
||||
g_assert (!g_output_stream_is_closed (f1));
|
||||
g_assert (!g_output_stream_is_closed (f2));
|
||||
|
||||
g_object_unref (f1);
|
||||
|
||||
g_assert (!g_output_stream_is_closed (base));
|
||||
g_assert (!g_output_stream_is_closed (f2));
|
||||
|
||||
g_object_unref (f2);
|
||||
|
||||
g_assert (g_output_stream_is_closed (base));
|
||||
|
||||
g_object_unref (base);
|
||||
}
|
||||
|
||||
gpointer expected_obj;
|
||||
gpointer expected_data;
|
||||
gboolean callback_happened;
|
||||
|
||||
static void
|
||||
in_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert (object == expected_obj);
|
||||
g_assert (user_data == expected_data);
|
||||
g_assert (callback_happened == FALSE);
|
||||
|
||||
g_input_stream_close_finish (expected_obj, result, &error);
|
||||
g_assert (error == NULL);
|
||||
|
||||
callback_happened = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_input_async (void)
|
||||
{
|
||||
GInputStream *base, *f1, *f2;
|
||||
|
||||
base = g_memory_input_stream_new_from_data ("abcdefghijk", -1, NULL);
|
||||
f1 = g_buffered_input_stream_new (base);
|
||||
f2 = g_buffered_input_stream_new (base);
|
||||
|
||||
g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (f1), FALSE);
|
||||
|
||||
g_assert (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (f1)) == base);
|
||||
g_assert (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (f2)) == base);
|
||||
|
||||
g_assert (!g_input_stream_is_closed (base));
|
||||
g_assert (!g_input_stream_is_closed (f1));
|
||||
g_assert (!g_input_stream_is_closed (f2));
|
||||
|
||||
expected_obj = f1;
|
||||
expected_data = g_malloc (20);
|
||||
callback_happened = FALSE;
|
||||
g_input_stream_close_async (f1, 0, NULL, in_cb, expected_data);
|
||||
|
||||
g_assert (callback_happened == FALSE);
|
||||
while (g_main_context_pending (NULL))
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
g_assert (callback_happened == TRUE);
|
||||
|
||||
g_assert (!g_input_stream_is_closed (base));
|
||||
g_assert (!g_input_stream_is_closed (f2));
|
||||
g_free (expected_data);
|
||||
g_object_unref (f1);
|
||||
g_assert (!g_input_stream_is_closed (base));
|
||||
g_assert (!g_input_stream_is_closed (f2));
|
||||
|
||||
expected_obj = f2;
|
||||
expected_data = g_malloc (20);
|
||||
callback_happened = FALSE;
|
||||
g_input_stream_close_async (f2, 0, NULL, in_cb, expected_data);
|
||||
|
||||
g_assert (callback_happened == FALSE);
|
||||
while (g_main_context_pending (NULL))
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
g_assert (callback_happened == TRUE);
|
||||
|
||||
g_assert (g_input_stream_is_closed (base));
|
||||
g_assert (g_input_stream_is_closed (f2));
|
||||
g_free (expected_data);
|
||||
g_object_unref (f2);
|
||||
|
||||
g_assert (g_input_stream_is_closed (base));
|
||||
g_object_unref (base);
|
||||
}
|
||||
|
||||
static void
|
||||
out_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert (object == expected_obj);
|
||||
g_assert (user_data == expected_data);
|
||||
g_assert (callback_happened == FALSE);
|
||||
|
||||
g_output_stream_close_finish (expected_obj, result, &error);
|
||||
g_assert (error == NULL);
|
||||
|
||||
callback_happened = TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_output_async (void)
|
||||
{
|
||||
GOutputStream *base, *f1, *f2;
|
||||
|
||||
base = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||
f1 = g_buffered_output_stream_new (base);
|
||||
f2 = g_buffered_output_stream_new (base);
|
||||
|
||||
g_filter_output_stream_set_close_base_stream (G_FILTER_OUTPUT_STREAM (f1), FALSE);
|
||||
|
||||
g_assert (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (f1)) == base);
|
||||
g_assert (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (f2)) == base);
|
||||
|
||||
g_assert (!g_output_stream_is_closed (base));
|
||||
g_assert (!g_output_stream_is_closed (f1));
|
||||
g_assert (!g_output_stream_is_closed (f2));
|
||||
|
||||
expected_obj = f1;
|
||||
expected_data = g_malloc (20);
|
||||
callback_happened = FALSE;
|
||||
g_output_stream_close_async (f1, 0, NULL, out_cb, expected_data);
|
||||
|
||||
g_assert (callback_happened == FALSE);
|
||||
while (g_main_context_pending (NULL))
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
g_assert (callback_happened == TRUE);
|
||||
|
||||
g_assert (!g_output_stream_is_closed (base));
|
||||
g_assert (!g_output_stream_is_closed (f2));
|
||||
g_free (expected_data);
|
||||
g_object_unref (f1);
|
||||
g_assert (!g_output_stream_is_closed (base));
|
||||
g_assert (!g_output_stream_is_closed (f2));
|
||||
|
||||
expected_obj = f2;
|
||||
expected_data = g_malloc (20);
|
||||
callback_happened = FALSE;
|
||||
g_output_stream_close_async (f2, 0, NULL, out_cb, expected_data);
|
||||
|
||||
g_assert (callback_happened == FALSE);
|
||||
while (g_main_context_pending (NULL))
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
g_assert (callback_happened == TRUE);
|
||||
|
||||
g_assert (g_output_stream_is_closed (base));
|
||||
g_assert (g_output_stream_is_closed (f2));
|
||||
g_free (expected_data);
|
||||
g_object_unref (f2);
|
||||
|
||||
g_assert (g_output_stream_is_closed (base));
|
||||
g_object_unref (base);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||
|
||||
g_type_init ();
|
||||
g_test_add_func ("/filter-stream/input", test_input_filter);
|
||||
g_test_add_func ("/filter-stream/output", test_output_filter);
|
||||
g_test_add_func ("/filter-stream/async-input", test_input_async);
|
||||
g_test_add_func ("/filter-stream/async-output", test_output_async);
|
||||
|
||||
return g_test_run();
|
||||
}
|
125
gio/tests/g-file-info.c
Normal file
125
gio/tests/g-file-info.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Authors: Tomas Bzatek <tbzatek@redhat.com>
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEST_NAME "Prilis zlutoucky kun"
|
||||
#define TEST_DISPLAY_NAME "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"
|
||||
#define TEST_SIZE 0xFFFFFFF0
|
||||
|
||||
static void
|
||||
test_assigned_values (GFileInfo *info)
|
||||
{
|
||||
const char *name, *display_name, *mistake;
|
||||
guint64 size;
|
||||
GFileType type;
|
||||
|
||||
/* Test for attributes presence */
|
||||
g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_NAME) == TRUE);
|
||||
g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME) == TRUE);
|
||||
g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE) == TRUE);
|
||||
g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME) == FALSE);
|
||||
|
||||
/* Retrieve data back and compare */
|
||||
|
||||
name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME);
|
||||
display_name = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
|
||||
mistake = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME);
|
||||
size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
|
||||
type = g_file_info_get_file_type (info);
|
||||
|
||||
g_assert_cmpstr (name, ==, TEST_NAME);
|
||||
g_assert_cmpstr (display_name, ==, TEST_DISPLAY_NAME);
|
||||
g_assert (mistake == NULL);
|
||||
g_assert_cmpint (size, ==, TEST_SIZE);
|
||||
g_assert_cmpstr (name, ==, g_file_info_get_name (info));
|
||||
g_assert_cmpstr (display_name, ==, g_file_info_get_display_name (info));
|
||||
g_assert_cmpint (size, ==, g_file_info_get_size (info) );
|
||||
g_assert_cmpint (type, ==, G_FILE_TYPE_DIRECTORY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_g_file_info (void)
|
||||
{
|
||||
GFileInfo *info;
|
||||
GFileInfo *info_dup;
|
||||
GFileInfo *info_copy;
|
||||
char **attr_list;
|
||||
|
||||
info = g_file_info_new ();
|
||||
|
||||
/* Test for empty instance */
|
||||
attr_list = g_file_info_list_attributes (info, NULL);
|
||||
g_assert (attr_list != NULL);
|
||||
g_assert (*attr_list == NULL);
|
||||
|
||||
g_file_info_set_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME, TEST_NAME);
|
||||
g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, TEST_DISPLAY_NAME);
|
||||
g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE, TEST_SIZE);
|
||||
g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
|
||||
|
||||
/* The attr list should not be empty now */
|
||||
attr_list = g_file_info_list_attributes (info, NULL);
|
||||
g_assert (attr_list != NULL);
|
||||
g_assert (*attr_list != NULL);
|
||||
|
||||
test_assigned_values (info);
|
||||
|
||||
/* Test dups */
|
||||
info_dup = g_file_info_dup (info);
|
||||
g_assert (info_dup != NULL);
|
||||
test_assigned_values (info_dup);
|
||||
|
||||
info_copy = g_file_info_new ();
|
||||
g_file_info_copy_into (info_dup, info_copy);
|
||||
g_assert (info_copy != NULL);
|
||||
test_assigned_values (info_copy);
|
||||
|
||||
/* Test remove attribute */
|
||||
g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) == FALSE);
|
||||
g_file_info_set_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER, 10);
|
||||
g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) == TRUE);
|
||||
|
||||
g_file_info_remove_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
|
||||
g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) == FALSE);
|
||||
|
||||
g_object_unref (info);
|
||||
g_object_unref (info_dup);
|
||||
g_object_unref (info_copy);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/g-file-info/test_g_file_info", test_g_file_info);
|
||||
|
||||
return g_test_run();
|
||||
}
|
538
gio/tests/g-file.c
Normal file
538
gio/tests/g-file.c
Normal file
@@ -0,0 +1,538 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Authors: Tomas Bzatek <tbzatek@redhat.com>
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct TestPathsWithOper {
|
||||
const char *path1;
|
||||
gboolean equal;
|
||||
gboolean use_uri;
|
||||
const char *path2;
|
||||
const char *path3;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* TODO:
|
||||
* - test on Windows
|
||||
*
|
||||
**/
|
||||
|
||||
static void
|
||||
test_g_file_new_null (void)
|
||||
{
|
||||
const char *paths[] = {"/",
|
||||
"/tmp///",
|
||||
"/non-existent-file",
|
||||
"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88",
|
||||
NULL
|
||||
};
|
||||
const char *uris[] = {"file:///",
|
||||
"file:///tmp///",
|
||||
"non-existent-uri:///some-dir/",
|
||||
"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88",
|
||||
NULL
|
||||
};
|
||||
|
||||
GFile *file = NULL;
|
||||
|
||||
int i = 0;
|
||||
while (paths[i])
|
||||
{
|
||||
file = g_file_new_for_path (paths[i++]);
|
||||
g_assert (file != NULL);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (uris[i])
|
||||
{
|
||||
file = g_file_new_for_uri (uris[i++]);
|
||||
g_assert (file != NULL);
|
||||
g_object_unref(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
compare_two_files (const gboolean use_uri, const char *path1, const char *path2)
|
||||
{
|
||||
GFile *file1 = NULL;
|
||||
GFile *file2 = NULL;
|
||||
gboolean equal;
|
||||
|
||||
if (use_uri)
|
||||
{
|
||||
file1 = g_file_new_for_uri (path1);
|
||||
file2 = g_file_new_for_uri (path2);
|
||||
}
|
||||
else
|
||||
{
|
||||
file1 = g_file_new_for_path (path1);
|
||||
file2 = g_file_new_for_path (path2);
|
||||
}
|
||||
|
||||
g_assert (file1 != NULL);
|
||||
g_assert (file2 != NULL);
|
||||
|
||||
equal = g_file_equal (file1, file2);
|
||||
|
||||
g_object_unref (file1);
|
||||
g_object_unref (file2);
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_new_for_path (void)
|
||||
{
|
||||
const struct TestPathsWithOper cmp_paths[] =
|
||||
{
|
||||
{"/", TRUE, 0, "/./"},
|
||||
{"//", TRUE, 0, "//"},
|
||||
{"//", TRUE, 0, "//./"},
|
||||
{"/", TRUE, 0, "/.//"},
|
||||
{"/", TRUE, 0, "/././"},
|
||||
{"/tmp", TRUE, 0, "/tmp/d/../"},
|
||||
{"/", TRUE, 0, "/somedir/../"},
|
||||
{"/", FALSE, 0, "/somedir/.../"},
|
||||
{"//tmp/dir1", TRUE, 0, "//tmp/dir1"},
|
||||
{"/tmp/dir1", TRUE, 0, "///tmp/dir1"},
|
||||
{"/tmp/dir1", TRUE, 0, "////tmp/dir1"},
|
||||
{"/tmp/dir1", TRUE, 0, "/tmp/./dir1"},
|
||||
{"/tmp/dir1", TRUE, 0, "/tmp//dir1"},
|
||||
{"/tmp/dir1", TRUE, 0, "/tmp///dir1///"},
|
||||
{"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", TRUE, 0, "/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/"}
|
||||
};
|
||||
|
||||
guint i;
|
||||
for (i = 0; i < G_N_ELEMENTS (cmp_paths); i++)
|
||||
{
|
||||
gboolean equal = compare_two_files (FALSE, cmp_paths[i].path1, cmp_paths[i].path2);
|
||||
g_assert_cmpint (equal, ==, cmp_paths[i].equal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_g_file_new_for_uri (void)
|
||||
{
|
||||
const struct TestPathsWithOper cmp_uris[] = {
|
||||
{"file:///", TRUE, 0, "file:///./"},
|
||||
{"file:////", TRUE, 0, "file:////"},
|
||||
{"file:////", TRUE, 0, "file:////./"},
|
||||
{"file:///", TRUE, 0, "file:///.//"},
|
||||
{"file:///", TRUE, 0, "file:///././"},
|
||||
{"file:///tmp", TRUE, 0, "file:///tmp/d/../"},
|
||||
{"file:///", TRUE, 0, "file:///somedir/../"},
|
||||
{"file:///", FALSE, 0, "file:///somedir/.../"},
|
||||
{"file:////tmp/dir1", TRUE, 0, "file:////tmp/dir1"},
|
||||
{"file:///tmp/dir1", TRUE, 0, "file:///tmp/./dir1"},
|
||||
{"file:///tmp/dir1", TRUE, 0, "file:///tmp//dir1"},
|
||||
{"file:///tmp/dir1", TRUE, 0, "file:///tmp///dir1///"},
|
||||
{"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", TRUE, 0, "file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/"}
|
||||
};
|
||||
|
||||
guint i;
|
||||
for (i = 0; i < G_N_ELEMENTS (cmp_uris); i++)
|
||||
{
|
||||
gboolean equal = compare_two_files (TRUE, cmp_uris[i].path1, cmp_uris[i].path2);
|
||||
g_assert_cmpint (equal, ==, cmp_uris[i].equal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
dup_equals (const gboolean use_uri, const char *path)
|
||||
{
|
||||
GFile *file1 = NULL;
|
||||
GFile *file2 = NULL;
|
||||
gboolean equal;
|
||||
|
||||
if (use_uri)
|
||||
file1 = g_file_new_for_uri (path);
|
||||
else
|
||||
file1 = g_file_new_for_path (path);
|
||||
|
||||
g_assert (file1 != NULL);
|
||||
|
||||
file2 = g_file_dup (file1);
|
||||
|
||||
g_assert (file2 != NULL);
|
||||
|
||||
equal = g_file_equal (file1, file2);
|
||||
|
||||
g_object_unref (file1);
|
||||
g_object_unref (file2);
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_dup (void)
|
||||
{
|
||||
const struct TestPathsWithOper dup_paths[] =
|
||||
{
|
||||
{"/", 0, FALSE, ""},
|
||||
{"file:///", 0, TRUE, ""},
|
||||
{"totalnonsense", 0, FALSE, ""},
|
||||
{"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, ""},
|
||||
{"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", 0, TRUE, ""},
|
||||
};
|
||||
|
||||
guint i;
|
||||
for (i = 0; i < G_N_ELEMENTS (dup_paths); i++)
|
||||
{
|
||||
gboolean equal = dup_equals (dup_paths[i].use_uri, dup_paths[i].path1);
|
||||
g_assert (equal == TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
parse_check_utf8 (const gboolean use_uri, const char *path, const char *result_parse_name)
|
||||
{
|
||||
GFile *file1 = NULL;
|
||||
GFile *file2 = NULL;
|
||||
char *parsed_name;
|
||||
gboolean is_utf8_valid;
|
||||
gboolean equal;
|
||||
|
||||
if (use_uri)
|
||||
file1 = g_file_new_for_uri (path);
|
||||
else
|
||||
file1 = g_file_new_for_path (path);
|
||||
|
||||
g_assert (file1 != NULL);
|
||||
|
||||
parsed_name = g_file_get_parse_name (file1);
|
||||
|
||||
g_assert (parsed_name != NULL);
|
||||
|
||||
/* UTF-8 validation */
|
||||
is_utf8_valid = g_utf8_validate (parsed_name, -1, NULL);
|
||||
g_assert (is_utf8_valid == TRUE);
|
||||
|
||||
if (result_parse_name)
|
||||
g_assert_cmpstr (parsed_name, ==, result_parse_name);
|
||||
|
||||
file2 = g_file_parse_name (parsed_name);
|
||||
|
||||
g_assert (file2 != NULL);
|
||||
|
||||
equal = g_file_equal (file1, file2);
|
||||
|
||||
g_object_unref (file1);
|
||||
g_object_unref (file2);
|
||||
|
||||
g_free (parsed_name);
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_get_parse_name_utf8 (void)
|
||||
{
|
||||
const struct TestPathsWithOper strings[] =
|
||||
{
|
||||
{"/", 0, FALSE, "/"},
|
||||
{"file:///", 0, TRUE, "/"},
|
||||
{"totalnonsense", 0, FALSE, NULL},
|
||||
{"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, NULL /* Depends on local file encoding */},
|
||||
{"file:///invalid%08/UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", 0, TRUE, "file:///invalid%08/UTF-8%20p\xc5\x99\xc3\xadli\xc5\xa1%20\xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd%20k\xc5\xaf\xc5\x88"},
|
||||
};
|
||||
|
||||
guint i;
|
||||
for (i = 0; i < G_N_ELEMENTS (strings); i++)
|
||||
{
|
||||
gboolean equal = parse_check_utf8 (strings[i].use_uri, strings[i].path1, strings[i].path2);
|
||||
g_assert (equal == TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
resolve_arg (const gboolean is_uri_only, const char *arg)
|
||||
{
|
||||
GFile *file1 = NULL;
|
||||
char *uri = NULL;
|
||||
char *path = NULL;
|
||||
char *s = NULL;
|
||||
|
||||
file1 = g_file_new_for_commandline_arg (arg);
|
||||
g_assert (file1 != NULL);
|
||||
|
||||
/* Test if we get URI string */
|
||||
uri = g_file_get_uri (file1);
|
||||
g_assert_cmpstr (uri, !=, NULL);
|
||||
g_print ("%s\n",uri);
|
||||
|
||||
/* Test if we get correct value of the local path */
|
||||
path = g_file_get_path (file1);
|
||||
if (is_uri_only)
|
||||
g_assert_cmpstr (path, ==, NULL);
|
||||
else
|
||||
g_assert (g_path_is_absolute (path) == TRUE);
|
||||
|
||||
/* Get the URI scheme and compare it with expected one */
|
||||
s = g_file_get_uri_scheme (file1);
|
||||
|
||||
g_object_unref (file1);
|
||||
g_free (uri);
|
||||
g_free (path);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_new_for_commandline_arg (void)
|
||||
{
|
||||
/* TestPathsWithOper.use_uri represents IsURIOnly here */
|
||||
const struct TestPathsWithOper arg_data[] =
|
||||
{
|
||||
{"./", 0, FALSE, "file"},
|
||||
{"../", 0, FALSE, "file"},
|
||||
{"/tmp", 0, FALSE, "file"},
|
||||
{"//UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, "file"},
|
||||
{"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", 0, FALSE, "file"},
|
||||
#if 0
|
||||
{"http://www.gtk.org/", 0, TRUE, "http"},
|
||||
{"ftp://user:pass@ftp.gimp.org/", 0, TRUE, "ftp"},
|
||||
#endif
|
||||
};
|
||||
GFile *file;
|
||||
char *resolved;
|
||||
char *cwd;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (arg_data); i++)
|
||||
{
|
||||
char *s = resolve_arg (arg_data[i].use_uri, arg_data[i].path1);
|
||||
g_assert_cmpstr (s, ==, arg_data[i].path2);
|
||||
g_free (s);
|
||||
}
|
||||
|
||||
/* Manual test for getting correct cwd */
|
||||
file = g_file_new_for_commandline_arg ("./");
|
||||
resolved = g_file_get_path (file);
|
||||
cwd = g_get_current_dir ();
|
||||
g_assert_cmpstr (resolved, ==, cwd);
|
||||
g_object_unref (file);
|
||||
g_free (resolved);
|
||||
g_free (cwd);
|
||||
}
|
||||
|
||||
static char*
|
||||
get_relative_path (const gboolean use_uri, const gboolean should_have_prefix, const char *dir1, const char *dir2)
|
||||
{
|
||||
GFile *file1 = NULL;
|
||||
GFile *file2 = NULL;
|
||||
GFile *file3 = NULL;
|
||||
gboolean has_prefix = FALSE;
|
||||
char *relative_path = NULL;
|
||||
|
||||
if (use_uri)
|
||||
{
|
||||
file1 = g_file_new_for_uri (dir1);
|
||||
file2 = g_file_new_for_uri (dir2);
|
||||
}
|
||||
else
|
||||
{
|
||||
file1 = g_file_new_for_path (dir1);
|
||||
file2 = g_file_new_for_path (dir2);
|
||||
}
|
||||
|
||||
g_assert (file1 != NULL);
|
||||
g_assert (file2 != NULL);
|
||||
|
||||
has_prefix = g_file_has_prefix (file2, file1);
|
||||
g_print ("%s %s\n", dir1, dir2);
|
||||
g_assert (has_prefix == should_have_prefix);
|
||||
|
||||
relative_path = g_file_get_relative_path (file1, file2);
|
||||
if (should_have_prefix)
|
||||
{
|
||||
g_assert (relative_path != NULL);
|
||||
|
||||
file3 = g_file_resolve_relative_path (file1, relative_path);
|
||||
g_assert (g_file_equal (file2, file3) == TRUE);
|
||||
}
|
||||
|
||||
if (file1)
|
||||
g_object_unref (file1);
|
||||
if (file2)
|
||||
g_object_unref (file2);
|
||||
if (file3)
|
||||
g_object_unref (file3);
|
||||
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_has_prefix (void)
|
||||
{
|
||||
/* TestPathsWithOper.equal represents here if the dir belongs to the directory structure */
|
||||
const struct TestPathsWithOper dirs[] =
|
||||
{
|
||||
/* path1 equal uri path2 path3 */
|
||||
{"/dir1", TRUE, FALSE, "/dir1/dir2/dir3/", "dir2/dir3"},
|
||||
{"/dir1/", TRUE, FALSE, "/dir1/dir2/dir3/", "dir2/dir3"},
|
||||
{"/dir1", TRUE, FALSE, "/dir1/dir2/dir3", "dir2/dir3"},
|
||||
{"/dir1/", TRUE, FALSE, "/dir1/dir2/dir3", "dir2/dir3"},
|
||||
{"/tmp/", FALSE, FALSE, "/something/", NULL},
|
||||
{"/dir1/dir2", FALSE, FALSE, "/dir1/", NULL},
|
||||
{"//dir1/new", TRUE, FALSE, "//dir1/new/dir2/dir3", "dir2/dir3"},
|
||||
{"/dir/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", TRUE, FALSE, "/dir/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/dir2", "dir2"},
|
||||
{"file:///dir1", TRUE, TRUE, "file:///dir1/dir2/dir3/", "dir2/dir3"},
|
||||
{"file:///dir1/", TRUE, TRUE, "file:///dir1/dir2/dir3/", "dir2/dir3"},
|
||||
{"file:///dir1", TRUE, TRUE, "file:///dir1/dir2/dir3", "dir2/dir3"},
|
||||
{"file:///dir1/", TRUE, TRUE, "file:///dir1/dir2/dir3", "dir2/dir3"},
|
||||
{"file:///tmp/", FALSE, TRUE, "file:///something/", NULL},
|
||||
{"file:///dir1/dir2", FALSE, TRUE, "file:///dir1/", NULL},
|
||||
{"file:////dir1/new", TRUE, TRUE, "file:////dir1/new/dir2/dir3", "dir2/dir3"},
|
||||
{"file:///dir/UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", TRUE, TRUE, "file:///dir/UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/dir2", "dir2"},
|
||||
#if 0
|
||||
{"dav://www.gtk.org/plan/", TRUE, TRUE, "dav://www.gtk.org/plan/meetings/20071218.txt", "meetings/20071218.txt"},
|
||||
{"dav://www.gtk.org/plan/meetings", TRUE, TRUE, "dav://www.gtk.org/plan/meetings/20071218.txt", "20071218.txt"},
|
||||
#endif
|
||||
};
|
||||
|
||||
guint i;
|
||||
for (i = 0; i < G_N_ELEMENTS (dirs); i++)
|
||||
{
|
||||
char *s = get_relative_path (dirs[i].use_uri, dirs[i].equal, dirs[i].path1, dirs[i].path2);
|
||||
if (dirs[i].equal)
|
||||
g_assert_cmpstr (s, ==, dirs[i].path3);
|
||||
g_free (s);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
roundtrip_parent_child (const gboolean use_uri, const gboolean under_root_descending,
|
||||
const char *path, const char *dir_holder)
|
||||
{
|
||||
GFile *files[6] = {NULL};
|
||||
guint i;
|
||||
|
||||
if (use_uri)
|
||||
{
|
||||
files[0] = g_file_new_for_uri (path);
|
||||
files[1] = g_file_new_for_uri (path);
|
||||
}
|
||||
else
|
||||
{
|
||||
files[0] = g_file_new_for_path (path);
|
||||
files[1] = g_file_new_for_path (path);
|
||||
}
|
||||
|
||||
g_assert (files[0] != NULL);
|
||||
g_assert (files[1] != NULL);
|
||||
|
||||
files[2] = g_file_get_child (files[1], dir_holder);
|
||||
g_assert (files[2] != NULL);
|
||||
|
||||
files[3] = g_file_get_parent (files[2]);
|
||||
g_assert (files[3] != NULL);
|
||||
g_assert (g_file_equal (files[3], files[0]) == TRUE);
|
||||
|
||||
files[4] = g_file_get_parent (files[3]);
|
||||
/* Don't go lower beyond the root */
|
||||
if (under_root_descending)
|
||||
g_assert (files[4] == NULL);
|
||||
else
|
||||
{
|
||||
g_assert (files[4] != NULL);
|
||||
|
||||
files[5] = g_file_get_child (files[4], dir_holder);
|
||||
g_assert (files[5] != NULL);
|
||||
g_assert (g_file_equal (files[5], files[0]) == TRUE);
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (files); i++)
|
||||
{
|
||||
if (files[i])
|
||||
g_object_unref (files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_get_parent_child (void)
|
||||
{
|
||||
const struct TestPathsWithOper paths[] =
|
||||
{
|
||||
/* path root_desc uri dir_holder */
|
||||
{"/dir1/dir", FALSE, FALSE, "dir"},
|
||||
{"/dir", FALSE, FALSE, "dir"},
|
||||
{"/", TRUE, FALSE, "dir"},
|
||||
{"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/", FALSE, FALSE, "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"},
|
||||
{"file:///dir1/dir", FALSE, TRUE, "dir"},
|
||||
{"file:///dir", FALSE, TRUE, "dir"},
|
||||
{"file:///", TRUE, TRUE, "dir"},
|
||||
{"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", FALSE, TRUE, "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"},
|
||||
{"dav://www.gtk.org/plan/meetings", FALSE, TRUE, "meetings"},
|
||||
};
|
||||
|
||||
guint i;
|
||||
for (i = 0; i < G_N_ELEMENTS (paths); i++)
|
||||
roundtrip_parent_child (paths[i].use_uri, paths[i].equal, paths[i].path1, paths[i].path2);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
|
||||
/* Testing whether g_file_new_for_path() or g_file_new_for_uri() always returns non-NULL result */
|
||||
g_test_add_func ("/g-file/test_g_file_new_null", test_g_file_new_null);
|
||||
|
||||
/* Testing whether the g_file_new_for_path() correctly canonicalizes strings and two files equals (g_file_equal()) */
|
||||
g_test_add_func ("/g-file/test_g_file_new_for_path", test_g_file_new_for_path);
|
||||
|
||||
/* Testing whether the g_file_new_for_uri() correctly canonicalizes strings and two files equals (g_file_equal()) */
|
||||
g_test_add_func ("/g-file/test_g_file_new_for_uri", test_g_file_new_for_uri);
|
||||
|
||||
/* Testing g_file_dup() equals original file via g_file_equal() */
|
||||
g_test_add_func ("/g-file/test_g_file_dup", test_g_file_dup);
|
||||
|
||||
/* Testing g_file_get_parse_name() to return correct UTF-8 string */
|
||||
g_test_add_func ("/g-file/test_g_file_get_parse_name_utf8", test_g_file_get_parse_name_utf8);
|
||||
|
||||
/* Testing g_file_new_for_commandline_arg() for correct relavive path resolution and correct path/URI guess */
|
||||
g_test_add_func ("/g-file/test_g_file_new_for_commandline_arg", test_g_file_new_for_commandline_arg);
|
||||
|
||||
/* Testing g_file_has_prefix(), g_file_get_relative_path() and g_file_resolve_relative_path() to return and process correct relative paths */
|
||||
g_test_add_func ("/g-file/test_g_file_has_prefix", test_g_file_has_prefix);
|
||||
|
||||
/* Testing g_file_get_parent() and g_file_get_child() */
|
||||
g_test_add_func ("/g-file/test_g_file_get_parent_child", test_g_file_get_parent_child);
|
||||
|
||||
return g_test_run();
|
||||
}
|
245
gio/tests/g-icon.c
Normal file
245
gio/tests/g-icon.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* GLib testing framework examples and tests
|
||||
*
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*
|
||||
* Authors: David Zeuthen <davidz@redhat.com>
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
test_g_icon_serialize (void)
|
||||
{
|
||||
GIcon *icon;
|
||||
GIcon *icon2;
|
||||
GIcon *icon3;
|
||||
GIcon *icon4;
|
||||
GIcon *icon5;
|
||||
GEmblem *emblem1;
|
||||
GEmblem *emblem2;
|
||||
const char *uri;
|
||||
GFile *location;
|
||||
char *data;
|
||||
GError *error;
|
||||
|
||||
error = NULL;
|
||||
|
||||
/* check that GFileIcon and GThemedIcon serialize to the encoding specified */
|
||||
|
||||
uri = "file:///some/native/path/to/an/icon.png";
|
||||
location = g_file_new_for_uri (uri);
|
||||
icon = g_file_icon_new (location);
|
||||
data = g_icon_to_string (icon);
|
||||
g_assert_cmpstr (data, ==, "/some/native/path/to/an/icon.png");
|
||||
icon2 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_free (data);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (location);
|
||||
|
||||
uri = "file:///some/native/path/to/an/icon with spaces.png";
|
||||
location = g_file_new_for_uri (uri);
|
||||
icon = g_file_icon_new (location);
|
||||
data = g_icon_to_string (icon);
|
||||
g_assert_cmpstr (data, ==, "/some/native/path/to/an/icon with spaces.png");
|
||||
icon2 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_free (data);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (location);
|
||||
|
||||
uri = "sftp:///some/non-native/path/to/an/icon.png";
|
||||
location = g_file_new_for_uri (uri);
|
||||
icon = g_file_icon_new (location);
|
||||
data = g_icon_to_string (icon);
|
||||
g_assert_cmpstr (data, ==, "sftp:///some/non-native/path/to/an/icon.png");
|
||||
icon2 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_free (data);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (location);
|
||||
|
||||
#if 0
|
||||
uri = "sftp:///some/non-native/path/to/an/icon with spaces.png";
|
||||
location = g_file_new_for_uri (uri);
|
||||
icon = g_file_icon_new (location);
|
||||
data = g_icon_to_string (icon);
|
||||
g_assert_cmpstr (data, ==, "sftp:///some/non-native/path/to/an/icon%20with%20spaces.png");
|
||||
icon2 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_free (data);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (location);
|
||||
#endif
|
||||
|
||||
icon = g_themed_icon_new ("network-server");
|
||||
data = g_icon_to_string (icon);
|
||||
g_assert_cmpstr (data, ==, "network-server");
|
||||
icon2 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_free (data);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
|
||||
/* Check that we can serialize from well-known specified formats */
|
||||
icon = g_icon_new_for_string ("network-server%", &error);
|
||||
g_assert_no_error (error);
|
||||
icon2 = g_themed_icon_new ("network-server%");
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
|
||||
icon = g_icon_new_for_string ("/path/to/somewhere.png", &error);
|
||||
g_assert_no_error (error);
|
||||
location = g_file_new_for_commandline_arg ("/path/to/somewhere.png");
|
||||
icon2 = g_file_icon_new (location);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (location);
|
||||
|
||||
icon = g_icon_new_for_string ("/path/to/somewhere with whitespace.png", &error);
|
||||
g_assert_no_error (error);
|
||||
data = g_icon_to_string (icon);
|
||||
g_assert_cmpstr (data, ==, "/path/to/somewhere with whitespace.png");
|
||||
g_free (data);
|
||||
location = g_file_new_for_commandline_arg ("/path/to/somewhere with whitespace.png");
|
||||
icon2 = g_file_icon_new (location);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_object_unref (location);
|
||||
g_object_unref (icon2);
|
||||
location = g_file_new_for_commandline_arg ("/path/to/somewhere%20with%20whitespace.png");
|
||||
icon2 = g_file_icon_new (location);
|
||||
g_assert (!g_icon_equal (icon, icon2));
|
||||
g_object_unref (location);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (icon);
|
||||
|
||||
icon = g_icon_new_for_string ("sftp:///path/to/somewhere.png", &error);
|
||||
g_assert_no_error (error);
|
||||
data = g_icon_to_string (icon);
|
||||
g_assert_cmpstr (data, ==, "sftp:///path/to/somewhere.png");
|
||||
g_free (data);
|
||||
location = g_file_new_for_commandline_arg ("sftp:///path/to/somewhere.png");
|
||||
icon2 = g_file_icon_new (location);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (location);
|
||||
|
||||
#if 0
|
||||
icon = g_icon_new_for_string ("sftp:///path/to/somewhere with whitespace.png", &error);
|
||||
g_assert_no_error (error);
|
||||
data = g_icon_to_string (icon);
|
||||
g_assert_cmpstr (data, ==, "sftp:///path/to/somewhere%20with%20whitespace.png");
|
||||
g_free (data);
|
||||
location = g_file_new_for_commandline_arg ("sftp:///path/to/somewhere with whitespace.png");
|
||||
icon2 = g_file_icon_new (location);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_object_unref (location);
|
||||
g_object_unref (icon2);
|
||||
location = g_file_new_for_commandline_arg ("sftp:///path/to/somewhere%20with%20whitespace.png");
|
||||
icon2 = g_file_icon_new (location);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_object_unref (location);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (icon);
|
||||
#endif
|
||||
|
||||
/* Check that GThemedIcon serialization works */
|
||||
|
||||
icon = g_themed_icon_new ("network-server");
|
||||
g_themed_icon_append_name (G_THEMED_ICON (icon), "computer");
|
||||
data = g_icon_to_string (icon);
|
||||
icon2 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_free (data);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
|
||||
icon = g_themed_icon_new ("icon name with whitespace");
|
||||
g_themed_icon_append_name (G_THEMED_ICON (icon), "computer");
|
||||
data = g_icon_to_string (icon);
|
||||
icon2 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_free (data);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
|
||||
icon = g_themed_icon_new_with_default_fallbacks ("network-server-xyz");
|
||||
g_themed_icon_append_name (G_THEMED_ICON (icon), "computer");
|
||||
data = g_icon_to_string (icon);
|
||||
icon2 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_free (data);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
|
||||
/* Check that GEmblemedIcon serialization works */
|
||||
|
||||
icon = g_themed_icon_new ("face-smirk");
|
||||
icon2 = g_themed_icon_new ("emblem-important");
|
||||
g_themed_icon_append_name (G_THEMED_ICON (icon2), "emblem-shared");
|
||||
location = g_file_new_for_uri ("file:///some/path/somewhere.png");
|
||||
icon3 = g_file_icon_new (location);
|
||||
g_object_unref (location);
|
||||
emblem1 = g_emblem_new_with_origin (icon2, G_EMBLEM_ORIGIN_DEVICE);
|
||||
emblem2 = g_emblem_new_with_origin (icon3, G_EMBLEM_ORIGIN_LIVEMETADATA);
|
||||
icon4 = g_emblemed_icon_new (icon, emblem1);
|
||||
g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (icon4), emblem2);
|
||||
data = g_icon_to_string (icon4);
|
||||
icon5 = g_icon_new_for_string (data, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (g_icon_equal (icon4, icon5));
|
||||
g_object_unref (emblem1);
|
||||
g_object_unref (emblem2);
|
||||
g_object_unref (icon);
|
||||
g_object_unref (icon2);
|
||||
g_object_unref (icon3);
|
||||
g_object_unref (icon4);
|
||||
g_object_unref (icon5);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/g-icon/serialize", test_g_icon_serialize);
|
||||
|
||||
return g_test_run();
|
||||
}
|
183
gio/tests/httpd.c
Normal file
183
gio/tests/httpd.c
Normal file
@@ -0,0 +1,183 @@
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int port = 8080;
|
||||
static char *root = NULL;
|
||||
static GOptionEntry cmd_entries[] = {
|
||||
{"port", 'p', 0, G_OPTION_ARG_INT, &port,
|
||||
"Local port to bind to", NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static void
|
||||
send_error (GOutputStream *out,
|
||||
int error_code,
|
||||
const char *reason)
|
||||
{
|
||||
char *res;
|
||||
|
||||
res = g_strdup_printf ("HTTP/1.0 %d %s\r\n\r\n"
|
||||
"<html><head><title>%d %s</title></head>"
|
||||
"<body>%s</body></html>",
|
||||
error_code, reason,
|
||||
error_code, reason,
|
||||
reason);
|
||||
g_output_stream_write_all (out, res, strlen (res), NULL, NULL, NULL);
|
||||
g_free (res);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handler (GThreadedSocketService *service,
|
||||
GSocketConnection *connection,
|
||||
GSocketListener *listener,
|
||||
gpointer user_data)
|
||||
{
|
||||
GOutputStream *out;
|
||||
GInputStream *in;
|
||||
GFileInputStream *file_in;
|
||||
GDataInputStream *data;
|
||||
char *line, *escaped, *tmp, *query, *unescaped, *path, *version;
|
||||
GFile *f;
|
||||
GError *error;
|
||||
GFileInfo *info;
|
||||
GString *s;
|
||||
|
||||
in = g_io_stream_get_input_stream (G_IO_STREAM (connection));
|
||||
out = g_io_stream_get_output_stream (G_IO_STREAM (connection));
|
||||
|
||||
data = g_data_input_stream_new (in);
|
||||
/* Be tolerant of input */
|
||||
g_data_input_stream_set_newline_type (data, G_DATA_STREAM_NEWLINE_TYPE_ANY);
|
||||
|
||||
line = g_data_input_stream_read_line (data, NULL, NULL, NULL);
|
||||
|
||||
if (line == NULL)
|
||||
{
|
||||
send_error (out, 400, "Invalid request");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!g_str_has_prefix (line, "GET "))
|
||||
{
|
||||
send_error (out, 501, "Only GET implemented");
|
||||
goto out;
|
||||
}
|
||||
|
||||
escaped = line + 4; /* Skip "GET " */
|
||||
|
||||
version = NULL;
|
||||
tmp = strchr (escaped, ' ');
|
||||
if (tmp != NULL)
|
||||
{
|
||||
*tmp = 0;
|
||||
version = tmp + 1;
|
||||
}
|
||||
|
||||
query = strchr (escaped, '?');
|
||||
if (query != NULL)
|
||||
*query++ = 0;
|
||||
|
||||
unescaped = g_uri_unescape_string (escaped, NULL);
|
||||
path = g_build_filename (root, unescaped, NULL);
|
||||
g_free (unescaped);
|
||||
f = g_file_new_for_path (path);
|
||||
g_free (path);
|
||||
|
||||
error = NULL;
|
||||
file_in = g_file_read (f, NULL, &error);
|
||||
if (file_in == NULL)
|
||||
{
|
||||
send_error (out, 404, error->message);
|
||||
g_error_free (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = g_string_new ("HTTP/1.0 200 OK\r\n");
|
||||
info = g_file_input_stream_query_info (file_in,
|
||||
G_FILE_ATTRIBUTE_STANDARD_SIZE ","
|
||||
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
|
||||
NULL, NULL);
|
||||
if (info)
|
||||
{
|
||||
const char *content_type;
|
||||
char *mime_type;
|
||||
|
||||
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE))
|
||||
g_string_append_printf (s, "Content-Length: %"G_GINT64_FORMAT"\r\n",
|
||||
g_file_info_get_size (info));
|
||||
content_type = g_file_info_get_content_type (info);
|
||||
if (content_type)
|
||||
{
|
||||
mime_type = g_content_type_get_mime_type (content_type);
|
||||
if (mime_type)
|
||||
{
|
||||
g_string_append_printf (s, "Content-Type: %s\r\n",
|
||||
mime_type);
|
||||
g_free (mime_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_string_append (s, "\r\n");
|
||||
|
||||
if (g_output_stream_write_all (out,
|
||||
s->str, s->len,
|
||||
NULL, NULL, NULL))
|
||||
{
|
||||
g_output_stream_splice (out,
|
||||
G_INPUT_STREAM (file_in),
|
||||
0, NULL, NULL);
|
||||
}
|
||||
g_string_free (s, TRUE);
|
||||
|
||||
g_input_stream_close (G_INPUT_STREAM (file_in), NULL, NULL);
|
||||
g_object_unref (file_in);
|
||||
|
||||
out:
|
||||
g_object_unref (data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GSocketService *service;
|
||||
GOptionContext *context;
|
||||
GError *error = NULL;
|
||||
|
||||
g_type_init ();
|
||||
g_thread_init (NULL);
|
||||
|
||||
context = g_option_context_new ("<http root dir> - Simple HTTP server");
|
||||
g_option_context_add_main_entries (context, cmd_entries, NULL);
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error))
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("Root directory not specified\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
root = g_strdup (argv[1]);
|
||||
|
||||
service = g_threaded_socket_service_new (10);
|
||||
if (!g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service),
|
||||
port,
|
||||
NULL,
|
||||
&error))
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_print ("Http server listening on port %d\n", port);
|
||||
|
||||
g_signal_connect (service, "run", G_CALLBACK (handler), NULL);
|
||||
|
||||
g_main_loop_run (g_main_loop_new (NULL, FALSE));
|
||||
g_assert_not_reached ();
|
||||
}
|
1211
gio/tests/live-g-file.c
Normal file
1211
gio/tests/live-g-file.c
Normal file
File diff suppressed because it is too large
Load Diff
27
gio/tests/live-g-file.txt
Normal file
27
gio/tests/live-g-file.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
Before you start testing it would be good to explain how it works.
|
||||
|
||||
The script works in three modes:
|
||||
1. read-only (no special arguments) - suitable for read-only backends. Just
|
||||
create the sample structure using the second mode, pack it (tar -p is
|
||||
preffered to preserve unix modes) and put it on a reachable place.
|
||||
2. create-structure - only creates reference structure for later testing
|
||||
in read-only mode
|
||||
3. write mode - full test suite, creates testing structure and performs all
|
||||
read and write tests. Please note the delete/move tests are included
|
||||
in this mode and target directory structure is unusable after the script
|
||||
is finished.
|
||||
|
||||
|
||||
To see the list of available parameters just run 'live-g-file --help'
|
||||
|
||||
|
||||
Notes:
|
||||
- it's advised to clean target directory first, otherwise some tests might fail
|
||||
(i.e. the tests creating testing structure)
|
||||
|
||||
|
||||
Tested:
|
||||
- local filesystem (/tmp/...)
|
||||
- file:// uri (file:///tmp/...)
|
||||
- locatest:// gvfs backend (localtest:///tmp/...)
|
||||
- FAT16 filesystem (no POSIX extensions)
|
78
gio/tests/memory-input-stream.c
Normal file
78
gio/tests/memory-input-stream.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2007 Imendio AB
|
||||
* Authors: Tim Janik
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
test_read_chunks (void)
|
||||
{
|
||||
const char *data1 = "abcdefghijklmnopqrstuvwxyz";
|
||||
const char *data2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const char *result = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
char buffer[128];
|
||||
gsize bytes_read, pos, len, chunk_size;
|
||||
GError *error = NULL;
|
||||
GInputStream *stream;
|
||||
gboolean res;
|
||||
|
||||
stream = g_memory_input_stream_new ();
|
||||
|
||||
g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (stream),
|
||||
data1, -1, NULL);
|
||||
g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (stream),
|
||||
data2, -1, NULL);
|
||||
len = strlen (data1) + strlen (data2);
|
||||
|
||||
for (chunk_size = 1; chunk_size < len - 1; chunk_size++)
|
||||
{
|
||||
pos = 0;
|
||||
while (pos < len)
|
||||
{
|
||||
bytes_read = g_input_stream_read (stream, buffer, chunk_size, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpint (bytes_read, ==, MIN (chunk_size, len - pos));
|
||||
g_assert (strncmp (buffer, result + pos, bytes_read) == 0);
|
||||
|
||||
pos += bytes_read;
|
||||
}
|
||||
|
||||
g_assert_cmpint (pos, ==, len);
|
||||
res = g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, &error);
|
||||
g_assert_cmpint (res, ==, TRUE);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/memory-input-stream/read-chunks", test_read_chunks);
|
||||
|
||||
return g_test_run();
|
||||
}
|
100
gio/tests/memory-output-stream.c
Normal file
100
gio/tests/memory-output-stream.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Author: Matthias Clasen
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
test_truncate (void)
|
||||
{
|
||||
GOutputStream *mo;
|
||||
GDataOutputStream *o;
|
||||
int i;
|
||||
GError *error = NULL;
|
||||
|
||||
g_test_bug ("540423");
|
||||
|
||||
mo = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||
o = g_data_output_stream_new (mo);
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
g_data_output_stream_put_byte (o, 1, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
g_seekable_truncate (G_SEEKABLE (mo), 0, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
for (i = 0; i < 2000; i++)
|
||||
{
|
||||
g_data_output_stream_put_byte (o, 1, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
g_object_unref (o);
|
||||
g_object_unref (mo);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_size (void)
|
||||
{
|
||||
GOutputStream *mo;
|
||||
GDataOutputStream *o;
|
||||
int pos;
|
||||
|
||||
g_test_bug ("540459");
|
||||
|
||||
mo = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||
o = g_data_output_stream_new (mo);
|
||||
g_data_output_stream_put_byte (o, 1, NULL, NULL);
|
||||
pos = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mo));
|
||||
g_assert_cmpint (pos, ==, 1);
|
||||
|
||||
g_seekable_seek (G_SEEKABLE (mo), 0, G_SEEK_CUR, NULL, NULL);
|
||||
pos = g_seekable_tell (G_SEEKABLE (mo));
|
||||
g_assert_cmpint (pos, ==, 1);
|
||||
|
||||
g_test_bug ("540461");
|
||||
|
||||
g_seekable_seek (G_SEEKABLE (mo), 0, G_SEEK_SET, NULL, NULL);
|
||||
pos = g_seekable_tell (G_SEEKABLE (mo));
|
||||
g_assert_cmpint (pos, ==, 0);
|
||||
|
||||
pos = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mo));
|
||||
g_assert_cmpint (pos, ==, 1);
|
||||
|
||||
g_object_unref (o);
|
||||
g_object_unref (mo);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||
|
||||
g_test_add_func ("/memory-output-stream/truncate", test_truncate);
|
||||
g_test_add_func ("/memory-output-stream/get-data-size", test_data_size);
|
||||
|
||||
return g_test_run();
|
||||
}
|
293
gio/tests/readwrite.c
Normal file
293
gio/tests/readwrite.c
Normal file
@@ -0,0 +1,293 @@
|
||||
#include <glib/glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gio/gio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *original_data = "This is some test data that we can put in a file...";
|
||||
static const char *new_data = "new data..";
|
||||
|
||||
static void
|
||||
verify_pos (GIOStream *iostream, goffset expected_pos)
|
||||
{
|
||||
goffset pos;
|
||||
|
||||
pos = g_seekable_tell (G_SEEKABLE (iostream));
|
||||
g_assert_cmpint (pos, ==, expected_pos);
|
||||
|
||||
pos = g_seekable_tell (G_SEEKABLE (g_io_stream_get_input_stream (iostream)));
|
||||
g_assert_cmpint (pos, ==, expected_pos);
|
||||
|
||||
pos = g_seekable_tell (G_SEEKABLE (g_io_stream_get_output_stream (iostream)));
|
||||
g_assert_cmpint (pos, ==, expected_pos);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_iostream (GFileIOStream *file_iostream)
|
||||
{
|
||||
gboolean res;
|
||||
GIOStream *iostream;
|
||||
GError *error;
|
||||
GInputStream *in;
|
||||
GOutputStream *out;
|
||||
char buffer[1024];
|
||||
gsize n_bytes;
|
||||
char *modified_data;
|
||||
|
||||
iostream = G_IO_STREAM (file_iostream);
|
||||
|
||||
verify_pos (iostream, 0);
|
||||
|
||||
in = g_io_stream_get_input_stream (iostream);
|
||||
out = g_io_stream_get_output_stream (iostream);
|
||||
|
||||
res = g_input_stream_read_all (in, buffer, 20, &n_bytes, NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpint ((int)n_bytes, ==, 20);
|
||||
|
||||
g_assert (memcmp (buffer, original_data, 20) == 0);
|
||||
|
||||
verify_pos (iostream, 20);
|
||||
|
||||
res = g_seekable_seek (G_SEEKABLE (iostream),
|
||||
-10, G_SEEK_END,
|
||||
NULL, NULL);
|
||||
g_assert (res);
|
||||
verify_pos (iostream, strlen (original_data) - 10);
|
||||
|
||||
res = g_input_stream_read_all (in, buffer, 20, &n_bytes, NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpint ((int)n_bytes, ==, 10);
|
||||
g_assert (memcmp (buffer, original_data + strlen (original_data) - 10, 10) == 0);
|
||||
|
||||
verify_pos (iostream, strlen (original_data));
|
||||
|
||||
res = g_seekable_seek (G_SEEKABLE (iostream),
|
||||
10, G_SEEK_SET,
|
||||
NULL, NULL);
|
||||
|
||||
verify_pos (iostream, 10);
|
||||
|
||||
res = g_output_stream_write_all (out, new_data, strlen (new_data),
|
||||
&n_bytes, NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpint (n_bytes, ==, strlen (new_data));
|
||||
|
||||
verify_pos (iostream, 10 + strlen (new_data));
|
||||
|
||||
res = g_seekable_seek (G_SEEKABLE (iostream),
|
||||
0, G_SEEK_SET,
|
||||
NULL, NULL);
|
||||
g_assert (res);
|
||||
verify_pos (iostream, 0);
|
||||
|
||||
res = g_input_stream_read_all (in, buffer, strlen (original_data), &n_bytes, NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpint ((int)n_bytes, ==, strlen (original_data));
|
||||
buffer[n_bytes] = 0;
|
||||
|
||||
modified_data = g_strdup (original_data);
|
||||
memcpy (modified_data + 10, new_data, strlen (new_data));
|
||||
g_assert_cmpstr (buffer, ==, modified_data);
|
||||
|
||||
verify_pos (iostream, strlen (original_data));
|
||||
|
||||
res = g_seekable_seek (G_SEEKABLE (iostream),
|
||||
0, G_SEEK_SET,
|
||||
NULL, NULL);
|
||||
g_assert (res);
|
||||
verify_pos (iostream, 0);
|
||||
|
||||
res = g_output_stream_close (out, NULL, NULL);
|
||||
g_assert (res);
|
||||
|
||||
res = g_input_stream_read_all (in, buffer, 15, &n_bytes, NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpint ((int)n_bytes, ==, 15);
|
||||
g_assert (memcmp (buffer, modified_data, 15) == 0);
|
||||
|
||||
error = NULL;
|
||||
res = g_output_stream_write_all (out, new_data, strlen (new_data),
|
||||
&n_bytes, NULL, &error);
|
||||
g_assert (!res);
|
||||
g_assert (error != NULL);
|
||||
g_assert (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED));
|
||||
|
||||
error = NULL;
|
||||
res = g_io_stream_close (iostream, NULL, &error);
|
||||
g_assert (res && error == NULL);
|
||||
|
||||
g_free (modified_data);
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_open_readwrite (void)
|
||||
{
|
||||
char *tmp_file;
|
||||
int fd;
|
||||
gboolean res;
|
||||
GFileIOStream *file_iostream;
|
||||
char *path;
|
||||
GFile *file;
|
||||
GError *error;
|
||||
|
||||
fd = g_file_open_tmp ("readwrite_XXXXXX",
|
||||
&tmp_file, NULL);
|
||||
g_assert (fd != -1);
|
||||
close (fd);
|
||||
|
||||
res = g_file_set_contents (tmp_file,
|
||||
original_data, -1, NULL);
|
||||
g_assert (res);
|
||||
|
||||
path = g_build_filename (g_get_home_dir (), "g-a-nonexisting-file", NULL);
|
||||
file = g_file_new_for_path (path);
|
||||
g_free (path);
|
||||
error = NULL;
|
||||
file_iostream = g_file_open_readwrite (file, NULL, &error);
|
||||
g_assert (file_iostream == NULL);
|
||||
g_assert (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND));
|
||||
g_error_free (error);
|
||||
g_object_unref (file);
|
||||
|
||||
file = g_file_new_for_path (tmp_file);
|
||||
error = NULL;
|
||||
file_iostream = g_file_open_readwrite (file, NULL, &error);
|
||||
g_assert (file_iostream != NULL);
|
||||
|
||||
verify_iostream (file_iostream);
|
||||
|
||||
g_object_unref (file_iostream);
|
||||
|
||||
g_unlink (tmp_file);
|
||||
g_free (tmp_file);
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_create_readwrite (void)
|
||||
{
|
||||
char *tmp_file;
|
||||
int fd;
|
||||
gboolean res;
|
||||
GFileIOStream *file_iostream;
|
||||
GOutputStream *out;
|
||||
GFile *file;
|
||||
GError *error;
|
||||
gsize n_bytes;
|
||||
|
||||
fd = g_file_open_tmp ("readwrite_XXXXXX",
|
||||
&tmp_file, NULL);
|
||||
g_assert (fd != -1);
|
||||
close (fd);
|
||||
|
||||
file = g_file_new_for_path (tmp_file);
|
||||
error = NULL;
|
||||
file_iostream = g_file_create_readwrite (file, 0, NULL, &error);
|
||||
g_assert (file_iostream == NULL);
|
||||
g_assert (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS));
|
||||
|
||||
g_unlink (tmp_file);
|
||||
file_iostream = g_file_create_readwrite (file, 0, NULL, &error);
|
||||
g_assert (file_iostream != NULL);
|
||||
|
||||
out = g_io_stream_get_output_stream (G_IO_STREAM (file_iostream));
|
||||
res = g_output_stream_write_all (out, original_data, strlen (original_data),
|
||||
&n_bytes, NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpint (n_bytes, ==, strlen (original_data));
|
||||
|
||||
res = g_seekable_seek (G_SEEKABLE (file_iostream),
|
||||
0, G_SEEK_SET,
|
||||
NULL, NULL);
|
||||
g_assert (res);
|
||||
|
||||
verify_iostream (file_iostream);
|
||||
|
||||
g_object_unref (file_iostream);
|
||||
|
||||
g_unlink (tmp_file);
|
||||
g_free (tmp_file);
|
||||
}
|
||||
|
||||
static void
|
||||
test_g_file_replace_readwrite (void)
|
||||
{
|
||||
char *tmp_file, *backup, *data;
|
||||
int fd;
|
||||
gboolean res;
|
||||
GFileIOStream *file_iostream;
|
||||
GInputStream *in;
|
||||
GOutputStream *out;
|
||||
GFile *file;
|
||||
GError *error;
|
||||
char buffer[1024];
|
||||
gsize n_bytes;
|
||||
|
||||
fd = g_file_open_tmp ("readwrite_XXXXXX",
|
||||
&tmp_file, NULL);
|
||||
g_assert (fd != -1);
|
||||
close (fd);
|
||||
|
||||
res = g_file_set_contents (tmp_file,
|
||||
new_data, -1, NULL);
|
||||
g_assert (res);
|
||||
|
||||
file = g_file_new_for_path (tmp_file);
|
||||
error = NULL;
|
||||
file_iostream = g_file_replace_readwrite (file, NULL,
|
||||
TRUE, 0, NULL, &error);
|
||||
g_assert (file_iostream != NULL);
|
||||
|
||||
in = g_io_stream_get_input_stream (G_IO_STREAM (file_iostream));
|
||||
|
||||
/* Ensure its empty */
|
||||
res = g_input_stream_read_all (in, buffer, sizeof buffer, &n_bytes, NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpint ((int)n_bytes, ==, 0);
|
||||
|
||||
out = g_io_stream_get_output_stream (G_IO_STREAM (file_iostream));
|
||||
res = g_output_stream_write_all (out, original_data, strlen (original_data),
|
||||
&n_bytes, NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpint (n_bytes, ==, strlen (original_data));
|
||||
|
||||
res = g_seekable_seek (G_SEEKABLE (file_iostream),
|
||||
0, G_SEEK_SET,
|
||||
NULL, NULL);
|
||||
g_assert (res);
|
||||
|
||||
verify_iostream (file_iostream);
|
||||
|
||||
g_object_unref (file_iostream);
|
||||
|
||||
backup = g_strconcat (tmp_file, "~", NULL);
|
||||
res = g_file_get_contents (backup,
|
||||
&data,
|
||||
NULL, NULL);
|
||||
g_assert (res);
|
||||
g_assert_cmpstr (data, ==, new_data);
|
||||
g_free (data);
|
||||
g_unlink (backup);
|
||||
g_free (backup);
|
||||
|
||||
g_unlink (tmp_file);
|
||||
g_free (tmp_file);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/readwrite/test_g_file_open_readwrite",
|
||||
test_g_file_open_readwrite);
|
||||
g_test_add_func ("/readwrite/test_g_file_create_readwrite",
|
||||
test_g_file_create_readwrite);
|
||||
g_test_add_func ("/readwrite/test_g_file_replace_readwrite",
|
||||
test_g_file_replace_readwrite);
|
||||
|
||||
return g_test_run();
|
||||
}
|
506
gio/tests/resolver.c
Normal file
506
gio/tests/resolver.c
Normal file
@@ -0,0 +1,506 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <glib.h>
|
||||
#include "glibintl.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
static GResolver *resolver;
|
||||
static GCancellable *cancellable;
|
||||
static GMainLoop *loop;
|
||||
static int nlookups = 0;
|
||||
|
||||
static void G_GNUC_NORETURN
|
||||
usage (void)
|
||||
{
|
||||
fprintf (stderr, "Usage: resolver [-t] [-s] [hostname | IP | service/protocol/domain ] ...\n");
|
||||
fprintf (stderr, " resolver [-t] [-s] -c [hostname | IP | service/protocol/domain ]\n");
|
||||
fprintf (stderr, " Use -t to enable threading.\n");
|
||||
fprintf (stderr, " Use -s to do synchronous lookups.\n");
|
||||
fprintf (stderr, " Both together will result in simultaneous lookups in multiple threads\n");
|
||||
fprintf (stderr, " Use -c (and only a single resolvable argument) to test GSocketConnectable.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
G_LOCK_DEFINE_STATIC (response);
|
||||
|
||||
static void
|
||||
done_lookup (void)
|
||||
{
|
||||
nlookups--;
|
||||
if (nlookups == 0)
|
||||
{
|
||||
/* In the sync case we need to make sure we don't call
|
||||
* g_main_loop_quit before the loop is actually running...
|
||||
*/
|
||||
g_idle_add ((GSourceFunc)g_main_loop_quit, loop);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_resolved_name (const char *phys,
|
||||
char *name,
|
||||
GError *error)
|
||||
{
|
||||
G_LOCK (response);
|
||||
printf ("Address: %s\n", phys);
|
||||
if (error)
|
||||
{
|
||||
printf ("Error: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Name: %s\n", name);
|
||||
g_free (name);
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
done_lookup ();
|
||||
G_UNLOCK (response);
|
||||
}
|
||||
|
||||
static void
|
||||
print_resolved_addresses (const char *name,
|
||||
GList *addresses,
|
||||
GError *error)
|
||||
{
|
||||
char *phys;
|
||||
GList *a;
|
||||
|
||||
G_LOCK (response);
|
||||
printf ("Name: %s\n", name);
|
||||
if (error)
|
||||
{
|
||||
printf ("Error: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (a = addresses; a; a = a->next)
|
||||
{
|
||||
phys = g_inet_address_to_string (a->data);
|
||||
printf ("Address: %s\n", phys);
|
||||
g_free (phys);
|
||||
g_object_unref (a->data);
|
||||
}
|
||||
g_list_free (addresses);
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
done_lookup ();
|
||||
G_UNLOCK (response);
|
||||
}
|
||||
|
||||
static void
|
||||
print_resolved_service (const char *service,
|
||||
GList *targets,
|
||||
GError *error)
|
||||
{
|
||||
GList *t;
|
||||
|
||||
G_LOCK (response);
|
||||
printf ("Service: %s\n", service);
|
||||
if (error)
|
||||
{
|
||||
printf ("Error: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (t = targets; t; t = t->next)
|
||||
{
|
||||
printf ("%s:%u (pri %u, weight %u)\n",
|
||||
g_srv_target_get_hostname (t->data),
|
||||
g_srv_target_get_port (t->data),
|
||||
g_srv_target_get_priority (t->data),
|
||||
g_srv_target_get_weight (t->data));
|
||||
g_srv_target_free (t->data);
|
||||
}
|
||||
g_list_free (targets);
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
done_lookup ();
|
||||
G_UNLOCK (response);
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_one_sync (const char *arg)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (strchr (arg, '/'))
|
||||
{
|
||||
GList *targets;
|
||||
/* service/protocol/domain */
|
||||
char **parts = g_strsplit (arg, "/", 3);
|
||||
|
||||
if (!parts || !parts[2])
|
||||
usage ();
|
||||
|
||||
targets = g_resolver_lookup_service (resolver,
|
||||
parts[0], parts[1], parts[2],
|
||||
cancellable, &error);
|
||||
print_resolved_service (arg, targets, error);
|
||||
}
|
||||
else if (g_hostname_is_ip_address (arg))
|
||||
{
|
||||
GInetAddress *addr = g_inet_address_new_from_string (arg);
|
||||
char *name;
|
||||
|
||||
name = g_resolver_lookup_by_address (resolver, addr, cancellable, &error);
|
||||
print_resolved_name (arg, name, error);
|
||||
g_object_unref (addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
GList *addresses;
|
||||
|
||||
addresses = g_resolver_lookup_by_name (resolver, arg, cancellable, &error);
|
||||
print_resolved_addresses (arg, addresses, error);
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
lookup_thread (gpointer arg)
|
||||
{
|
||||
lookup_one_sync (arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
start_threaded_lookups (char **argv, int argc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
g_thread_create (lookup_thread, argv[i], FALSE, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
start_sync_lookups (char **argv, int argc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
lookup_one_sync (argv[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_by_addr_callback (GObject *source, GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *phys = user_data;
|
||||
GError *error = NULL;
|
||||
char *name;
|
||||
|
||||
name = g_resolver_lookup_by_address_finish (resolver, result, &error);
|
||||
print_resolved_name (phys, name, error);
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_by_name_callback (GObject *source, GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *name = user_data;
|
||||
GError *error = NULL;
|
||||
GList *addresses;
|
||||
|
||||
addresses = g_resolver_lookup_by_name_finish (resolver, result, &error);
|
||||
print_resolved_addresses (name, addresses, error);
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_service_callback (GObject *source, GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *service = user_data;
|
||||
GError *error = NULL;
|
||||
GList *targets;
|
||||
|
||||
targets = g_resolver_lookup_service_finish (resolver, result, &error);
|
||||
print_resolved_service (service, targets, error);
|
||||
}
|
||||
|
||||
static void
|
||||
start_async_lookups (char **argv, int argc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (strchr (argv[i], '/'))
|
||||
{
|
||||
/* service/protocol/domain */
|
||||
char **parts = g_strsplit (argv[i], "/", 3);
|
||||
|
||||
if (!parts || !parts[2])
|
||||
usage ();
|
||||
|
||||
g_resolver_lookup_service_async (resolver,
|
||||
parts[0], parts[1], parts[2],
|
||||
cancellable,
|
||||
lookup_service_callback, argv[i]);
|
||||
}
|
||||
else if (g_hostname_is_ip_address (argv[i]))
|
||||
{
|
||||
GInetAddress *addr = g_inet_address_new_from_string (argv[i]);
|
||||
|
||||
g_resolver_lookup_by_address_async (resolver, addr, cancellable,
|
||||
lookup_by_addr_callback, argv[i]);
|
||||
g_object_unref (addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_resolver_lookup_by_name_async (resolver, argv[i], cancellable,
|
||||
lookup_by_name_callback,
|
||||
argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_connectable_sockaddr (GSocketAddress *sockaddr,
|
||||
GError *error)
|
||||
{
|
||||
char *phys;
|
||||
|
||||
if (error)
|
||||
{
|
||||
printf ("Error: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else if (!G_IS_INET_SOCKET_ADDRESS (sockaddr))
|
||||
{
|
||||
printf ("Error: Unexpected sockaddr type '%s'\n", g_type_name_from_instance ((GTypeInstance *)sockaddr));
|
||||
g_object_unref (sockaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
GInetSocketAddress *isa = G_INET_SOCKET_ADDRESS (sockaddr);
|
||||
phys = g_inet_address_to_string (g_inet_socket_address_get_address (isa));
|
||||
printf ("Address: %s%s%s:%d\n",
|
||||
strchr (phys, ':') ? "[" : "", phys, strchr (phys, ':') ? "]" : "",
|
||||
g_inet_socket_address_get_port (isa));
|
||||
g_free (phys);
|
||||
g_object_unref (sockaddr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_sync_connectable (GSocketAddressEnumerator *enumerator)
|
||||
{
|
||||
GSocketAddress *sockaddr;
|
||||
GError *error = NULL;
|
||||
|
||||
while ((sockaddr = g_socket_address_enumerator_next (enumerator, cancellable, &error)))
|
||||
print_connectable_sockaddr (sockaddr, error);
|
||||
|
||||
g_object_unref (enumerator);
|
||||
done_lookup ();
|
||||
}
|
||||
|
||||
static void do_async_connectable (GSocketAddressEnumerator *enumerator);
|
||||
|
||||
static void
|
||||
got_next_async (GObject *source, GAsyncResult *result, gpointer user_data)
|
||||
{
|
||||
GSocketAddressEnumerator *enumerator = G_SOCKET_ADDRESS_ENUMERATOR (source);
|
||||
GSocketAddress *sockaddr;
|
||||
GError *error = NULL;
|
||||
|
||||
sockaddr = g_socket_address_enumerator_next_finish (enumerator, result, &error);
|
||||
if (sockaddr || error)
|
||||
print_connectable_sockaddr (sockaddr, error);
|
||||
if (sockaddr)
|
||||
do_async_connectable (enumerator);
|
||||
else
|
||||
{
|
||||
g_object_unref (enumerator);
|
||||
done_lookup ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_async_connectable (GSocketAddressEnumerator *enumerator)
|
||||
{
|
||||
g_socket_address_enumerator_next_async (enumerator, cancellable,
|
||||
got_next_async, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_connectable (const char *arg, gboolean synchronous)
|
||||
{
|
||||
char **parts;
|
||||
GSocketConnectable *connectable;
|
||||
GSocketAddressEnumerator *enumerator;
|
||||
|
||||
if (strchr (arg, '/'))
|
||||
{
|
||||
/* service/protocol/domain */
|
||||
parts = g_strsplit (arg, "/", 3);
|
||||
if (!parts || !parts[2])
|
||||
usage ();
|
||||
|
||||
connectable = g_network_service_new (parts[0], parts[1], parts[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
guint16 port;
|
||||
|
||||
parts = g_strsplit (arg, ":", 2);
|
||||
if (parts && parts[1])
|
||||
{
|
||||
arg = parts[0];
|
||||
port = strtoul (parts[1], NULL, 10);
|
||||
}
|
||||
else
|
||||
port = 0;
|
||||
|
||||
if (g_hostname_is_ip_address (arg))
|
||||
{
|
||||
GInetAddress *addr = g_inet_address_new_from_string (arg);
|
||||
GSocketAddress *sockaddr = g_inet_socket_address_new (addr, port);
|
||||
|
||||
g_object_unref (addr);
|
||||
connectable = G_SOCKET_CONNECTABLE (sockaddr);
|
||||
}
|
||||
else
|
||||
connectable = g_network_address_new (arg, port);
|
||||
}
|
||||
|
||||
enumerator = g_socket_connectable_enumerate (connectable);
|
||||
g_object_unref (connectable);
|
||||
|
||||
if (synchronous)
|
||||
do_sync_connectable (enumerator);
|
||||
else
|
||||
do_async_connectable (enumerator);
|
||||
}
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
static int cancel_fds[2];
|
||||
|
||||
static void
|
||||
interrupted (int sig)
|
||||
{
|
||||
signal (SIGINT, SIG_DFL);
|
||||
write (cancel_fds[1], "x", 1);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
async_cancel (GIOChannel *source, GIOCondition cond, gpointer cancel)
|
||||
{
|
||||
g_cancellable_cancel (cancel);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
gboolean threaded = FALSE, synchronous = FALSE;
|
||||
gboolean use_connectable = FALSE;
|
||||
#ifdef G_OS_UNIX
|
||||
GIOChannel *chan;
|
||||
guint watch;
|
||||
#endif
|
||||
|
||||
/* We can't use GOptionContext because we use the arguments to
|
||||
* decide whether or not to call g_thread_init().
|
||||
*/
|
||||
while (argc >= 2 && argv[1][0] == '-')
|
||||
{
|
||||
if (!strcmp (argv[1], "-t"))
|
||||
{
|
||||
g_thread_init (NULL);
|
||||
threaded = TRUE;
|
||||
}
|
||||
else if (!strcmp (argv[1], "-s"))
|
||||
synchronous = TRUE;
|
||||
else if (!strcmp (argv[1], "-c"))
|
||||
use_connectable = TRUE;
|
||||
else
|
||||
usage ();
|
||||
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
g_type_init ();
|
||||
|
||||
if (argc < 2 || (argc > 2 && use_connectable))
|
||||
usage ();
|
||||
|
||||
resolver = g_resolver_get_default ();
|
||||
|
||||
cancellable = g_cancellable_new ();
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
/* Set up cancellation; we want to cancel if the user ^C's the
|
||||
* program, but we can't cancel directly from an interrupt.
|
||||
*/
|
||||
signal (SIGINT, interrupted);
|
||||
|
||||
if (pipe (cancel_fds) == -1)
|
||||
{
|
||||
perror ("pipe");
|
||||
exit (1);
|
||||
}
|
||||
chan = g_io_channel_unix_new (cancel_fds[0]);
|
||||
watch = g_io_add_watch (chan, G_IO_IN, async_cancel, cancellable);
|
||||
g_io_channel_unref (chan);
|
||||
#endif
|
||||
|
||||
nlookups = argc - 1;
|
||||
loop = g_main_loop_new (NULL, TRUE);
|
||||
|
||||
if (use_connectable)
|
||||
do_connectable (argv[1], synchronous);
|
||||
else
|
||||
{
|
||||
if (threaded && synchronous)
|
||||
start_threaded_lookups (argv + 1, argc - 1);
|
||||
else if (synchronous)
|
||||
start_sync_lookups (argv + 1, argc - 1);
|
||||
else
|
||||
start_async_lookups (argv + 1, argc - 1);
|
||||
}
|
||||
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
g_source_remove (watch);
|
||||
#endif
|
||||
g_object_unref (cancellable);
|
||||
|
||||
return 0;
|
||||
}
|
163
gio/tests/send-data.c
Normal file
163
gio/tests/send-data.c
Normal file
@@ -0,0 +1,163 @@
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
GMainLoop *loop;
|
||||
|
||||
int cancel_timeout = 0;
|
||||
gboolean async = FALSE;
|
||||
gboolean graceful = FALSE;
|
||||
static GOptionEntry cmd_entries[] = {
|
||||
{"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
|
||||
"Cancel any op after the specified amount of seconds", NULL},
|
||||
{"async", 'a', 0, G_OPTION_ARG_NONE, &async,
|
||||
"Use async ops", NULL},
|
||||
{"graceful-disconnect", 'g', 0, G_OPTION_ARG_NONE, &graceful,
|
||||
"Use graceful disconnect", NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static gpointer
|
||||
cancel_thread (gpointer data)
|
||||
{
|
||||
GCancellable *cancellable = data;
|
||||
|
||||
g_usleep (1000*1000*cancel_timeout);
|
||||
g_print ("Cancelling\n");
|
||||
g_cancellable_cancel (cancellable);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
socket_address_to_string (GSocketAddress *address)
|
||||
{
|
||||
GInetAddress *inet_address;
|
||||
char *str, *res;
|
||||
int port;
|
||||
|
||||
inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
|
||||
str = g_inet_address_to_string (inet_address);
|
||||
port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
|
||||
res = g_strdup_printf ("%s:%d", str, port);
|
||||
g_free (str);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
async_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GAsyncResult **resp = user_data;
|
||||
*resp = g_object_ref (res);
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GOptionContext *context;
|
||||
GSocketClient *client;
|
||||
GSocketConnection *connection;
|
||||
GSocketAddress *address;
|
||||
GCancellable *cancellable;
|
||||
GOutputStream *out;
|
||||
GError *error = NULL;
|
||||
char buffer[1000];
|
||||
|
||||
g_type_init ();
|
||||
g_thread_init (NULL);
|
||||
|
||||
context = g_option_context_new (" <hostname>[:port] - send data to tcp host");
|
||||
g_option_context_add_main_entries (context, cmd_entries, NULL);
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error))
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], "Need to specify hostname");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (async)
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
if (cancel_timeout)
|
||||
{
|
||||
cancellable = g_cancellable_new ();
|
||||
g_thread_create (cancel_thread, cancellable, FALSE, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
cancellable = NULL;
|
||||
}
|
||||
|
||||
client = g_socket_client_new ();
|
||||
connection = g_socket_client_connect_to_host (client,
|
||||
argv[1],
|
||||
7777,
|
||||
cancellable, &error);
|
||||
if (connection == NULL)
|
||||
{
|
||||
g_printerr ("%s can't connect: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
address = g_socket_connection_get_remote_address (connection, &error);
|
||||
if (!address)
|
||||
{
|
||||
g_printerr ("Error getting remote address: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
g_print ("Connected to address: %s\n",
|
||||
socket_address_to_string (address));
|
||||
g_object_unref (address);
|
||||
|
||||
if (graceful)
|
||||
g_tcp_connection_set_graceful_disconnect (G_TCP_CONNECTION (connection), TRUE);
|
||||
|
||||
out = g_io_stream_get_output_stream (G_IO_STREAM (connection));
|
||||
|
||||
while (fgets(buffer, sizeof (buffer), stdin) != NULL)
|
||||
{
|
||||
if (!g_output_stream_write_all (out, buffer, strlen (buffer),
|
||||
NULL, cancellable, &error))
|
||||
{
|
||||
g_warning ("send error: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
error = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_print ("closing stream\n");
|
||||
if (async)
|
||||
{
|
||||
GAsyncResult *res;
|
||||
g_io_stream_close_async (G_IO_STREAM (connection),
|
||||
0, cancellable, async_cb, &res);
|
||||
g_main_loop_run (loop);
|
||||
if (!g_io_stream_close_finish (G_IO_STREAM (connection),
|
||||
res, &error))
|
||||
{
|
||||
g_object_unref (res);
|
||||
g_warning ("close error: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
g_object_unref (res);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!g_io_stream_close (G_IO_STREAM (connection), cancellable, &error))
|
||||
{
|
||||
g_warning ("close error: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
130
gio/tests/simple-async-result.c
Normal file
130
gio/tests/simple-async-result.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright © 2009 Ryan Lortie
|
||||
*
|
||||
* This program 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 licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* See the included COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static GObject *got_source;
|
||||
static GAsyncResult *got_result;
|
||||
static gpointer got_user_data;
|
||||
|
||||
static void
|
||||
ensure_destroyed (gpointer obj)
|
||||
{
|
||||
g_object_add_weak_pointer (obj, &obj);
|
||||
g_object_unref (obj);
|
||||
g_assert (obj == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
reset (void)
|
||||
{
|
||||
got_source = NULL;
|
||||
|
||||
if (got_result)
|
||||
ensure_destroyed (got_result);
|
||||
|
||||
got_result = NULL;
|
||||
got_user_data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
check (gpointer a, gpointer b, gpointer c)
|
||||
{
|
||||
g_assert (a == got_source);
|
||||
g_assert (b == got_result);
|
||||
g_assert (c == got_user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
callback_func (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
got_source = source;
|
||||
got_result = g_object_ref (result);
|
||||
got_user_data = user_data;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_simple_async_idle (gpointer user_data)
|
||||
{
|
||||
GSimpleAsyncResult *result;
|
||||
GObject *a, *b, *c;
|
||||
gboolean *ran = user_data;
|
||||
|
||||
a = g_object_new (G_TYPE_OBJECT, NULL);
|
||||
b = g_object_new (G_TYPE_OBJECT, NULL);
|
||||
c = g_object_new (G_TYPE_OBJECT, NULL);
|
||||
|
||||
result = g_simple_async_result_new (a, callback_func, b, test_simple_async_idle);
|
||||
check (NULL, NULL, NULL);
|
||||
g_simple_async_result_complete (result);
|
||||
check (a, result, b);
|
||||
g_object_unref (result);
|
||||
|
||||
g_assert (g_simple_async_result_is_valid (got_result, a, test_simple_async_idle));
|
||||
g_assert (!g_simple_async_result_is_valid (got_result, b, test_simple_async_idle));
|
||||
g_assert (!g_simple_async_result_is_valid (got_result, c, test_simple_async_idle));
|
||||
g_assert (!g_simple_async_result_is_valid (got_result, b, callback_func));
|
||||
g_assert (!g_simple_async_result_is_valid ((gpointer) a, NULL, NULL));
|
||||
reset ();
|
||||
reset ();
|
||||
reset ();
|
||||
|
||||
ensure_destroyed (a);
|
||||
ensure_destroyed (b);
|
||||
ensure_destroyed (c);
|
||||
|
||||
*ran = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_simple_async (void)
|
||||
{
|
||||
GSimpleAsyncResult *result;
|
||||
GObject *a, *b;
|
||||
gboolean ran_test_in_idle = FALSE;
|
||||
|
||||
g_idle_add (test_simple_async_idle, &ran_test_in_idle);
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
|
||||
g_assert (ran_test_in_idle);
|
||||
|
||||
a = g_object_new (G_TYPE_OBJECT, NULL);
|
||||
b = g_object_new (G_TYPE_OBJECT, NULL);
|
||||
|
||||
result = g_simple_async_result_new (a, callback_func, b, test_simple_async);
|
||||
check (NULL, NULL, NULL);
|
||||
g_simple_async_result_complete_in_idle (result);
|
||||
g_object_unref (result);
|
||||
check (NULL, NULL, NULL);
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
check (a, result, b);
|
||||
reset ();
|
||||
|
||||
ensure_destroyed (a);
|
||||
ensure_destroyed (b);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/gio/simple-async-result/test", test_simple_async);
|
||||
|
||||
return g_test_run();
|
||||
}
|
296
gio/tests/sleepy-stream.c
Normal file
296
gio/tests/sleepy-stream.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright © 2009 Codethink Limited
|
||||
*
|
||||
* This program 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 licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* See the included COPYING file for more information.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_PIECE_SIZE 100
|
||||
#define MAX_PIECES 60
|
||||
|
||||
static gchar *
|
||||
cook_piece (void)
|
||||
{
|
||||
char buffer[MAX_PIECE_SIZE * 2];
|
||||
gint symbols, i = 0;
|
||||
|
||||
symbols = g_test_rand_int_range (1, MAX_PIECE_SIZE + 1);
|
||||
|
||||
while (symbols--)
|
||||
{
|
||||
gint c = g_test_rand_int_range (0, 30);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 26:
|
||||
buffer[i++] = '\n';
|
||||
case 27:
|
||||
buffer[i++] = '\r';
|
||||
break;
|
||||
|
||||
case 28:
|
||||
buffer[i++] = '\r';
|
||||
case 29:
|
||||
buffer[i++] = '\n';
|
||||
break;
|
||||
|
||||
default:
|
||||
buffer[i++] = c + 'a';
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert_cmpint (i, <=, sizeof buffer);
|
||||
}
|
||||
|
||||
return g_strndup (buffer, i);
|
||||
}
|
||||
|
||||
static gchar **
|
||||
cook_pieces (void)
|
||||
{
|
||||
gchar **array;
|
||||
gint pieces;
|
||||
|
||||
pieces = g_test_rand_int_range (0, MAX_PIECES + 1);
|
||||
array = g_new (char *, pieces + 1);
|
||||
array[pieces] = NULL;
|
||||
|
||||
while (pieces--)
|
||||
array[pieces] = cook_piece ();
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GInputStream parent_instance;
|
||||
|
||||
gboolean built_to_fail;
|
||||
gchar **pieces;
|
||||
gint index;
|
||||
|
||||
const gchar *current;
|
||||
} SleepyStream;
|
||||
|
||||
typedef GInputStreamClass SleepyStreamClass;
|
||||
|
||||
GType sleepy_stream_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (SleepyStream, sleepy_stream, G_TYPE_INPUT_STREAM)
|
||||
|
||||
static gssize
|
||||
sleepy_stream_read (GInputStream *stream,
|
||||
void *buffer,
|
||||
gsize length,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
SleepyStream *sleepy = (SleepyStream *) stream;
|
||||
|
||||
if (sleepy->pieces[sleepy->index] == NULL)
|
||||
{
|
||||
if (sleepy->built_to_fail)
|
||||
{
|
||||
g_set_error (error, 0, 0, "fail");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sleepy->current)
|
||||
sleepy->current = sleepy->pieces[sleepy->index++];
|
||||
|
||||
length = MIN (strlen (sleepy->current), length);
|
||||
memcpy (buffer, sleepy->current, length);
|
||||
|
||||
sleepy->current += length;
|
||||
if (*sleepy->current == '\0')
|
||||
sleepy->current = NULL;
|
||||
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sleepy_stream_init (SleepyStream *sleepy)
|
||||
{
|
||||
sleepy->pieces = cook_pieces ();
|
||||
sleepy->built_to_fail = FALSE;
|
||||
sleepy->index = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sleepy_stream_finalize (GObject *object)
|
||||
{
|
||||
SleepyStream *sleepy = (SleepyStream *) object;
|
||||
|
||||
g_strfreev (sleepy->pieces);
|
||||
G_OBJECT_CLASS (sleepy_stream_parent_class)
|
||||
->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sleepy_stream_class_init (SleepyStreamClass *class)
|
||||
{
|
||||
G_OBJECT_CLASS (class)->finalize = sleepy_stream_finalize;
|
||||
class->read_fn = sleepy_stream_read;
|
||||
|
||||
/* no read_async implementation.
|
||||
* main thread will sleep while read runs in a worker.
|
||||
*/
|
||||
}
|
||||
|
||||
static SleepyStream *
|
||||
sleepy_stream_new (void)
|
||||
{
|
||||
return g_object_new (sleepy_stream_get_type (), NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
read_line (GDataInputStream *stream,
|
||||
GString *string,
|
||||
const gchar *eol,
|
||||
GError **error)
|
||||
{
|
||||
gsize length;
|
||||
int eol_len;
|
||||
char *str;
|
||||
|
||||
eol_len = 1 + (eol[1] != '\0');
|
||||
|
||||
str = g_data_input_stream_read_line (stream, &length, NULL, error);
|
||||
|
||||
if (str == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_assert (strstr (str, eol) == NULL);
|
||||
g_assert (strlen (str) == length);
|
||||
|
||||
g_string_append (string, str);
|
||||
g_string_append (string, eol);
|
||||
g_free (str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
build_comparison (GString *str,
|
||||
SleepyStream *stream)
|
||||
{
|
||||
/* build this for comparison */
|
||||
gint i;
|
||||
|
||||
for (i = 0; stream->pieces[i]; i++)
|
||||
g_string_append (str, stream->pieces[i]);
|
||||
|
||||
if (str->len && str->str[str->len - 1] != '\n')
|
||||
g_string_append_c (str, '\n');
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test (void)
|
||||
{
|
||||
SleepyStream *stream = sleepy_stream_new ();
|
||||
GDataInputStream *data;
|
||||
GError *error = NULL;
|
||||
GString *one;
|
||||
GString *two;
|
||||
|
||||
one = g_string_new (NULL);
|
||||
two = g_string_new (NULL);
|
||||
|
||||
data = g_data_input_stream_new (G_INPUT_STREAM (stream));
|
||||
g_data_input_stream_set_newline_type (data, G_DATA_STREAM_NEWLINE_TYPE_LF);
|
||||
build_comparison (one, stream);
|
||||
|
||||
while (read_line (data, two, "\n", &error));
|
||||
|
||||
g_assert_cmpstr (one->str, ==, two->str);
|
||||
g_string_free (one, TRUE);
|
||||
g_string_free (two, TRUE);
|
||||
g_object_unref (stream);
|
||||
g_object_unref (data);
|
||||
}
|
||||
|
||||
static GDataInputStream *data;
|
||||
static GString *one, *two;
|
||||
static GMainLoop *loop;
|
||||
static const gchar *eol;
|
||||
|
||||
static void
|
||||
asynch_ready (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gsize length;
|
||||
gchar *str;
|
||||
|
||||
g_assert (data == G_DATA_INPUT_STREAM (object));
|
||||
|
||||
str = g_data_input_stream_read_line_finish (data, result, &length, &error);
|
||||
|
||||
if (str == NULL)
|
||||
{
|
||||
g_main_loop_quit (loop);
|
||||
if (error)
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (length == strlen (str));
|
||||
g_string_append (two, str);
|
||||
g_string_append (two, eol);
|
||||
g_free (str);
|
||||
|
||||
/* MOAR!! */
|
||||
g_data_input_stream_read_line_async (data, 0, NULL, asynch_ready, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
asynch (void)
|
||||
{
|
||||
SleepyStream *sleepy = sleepy_stream_new ();
|
||||
|
||||
data = g_data_input_stream_new (G_INPUT_STREAM (sleepy));
|
||||
one = g_string_new (NULL);
|
||||
two = g_string_new (NULL);
|
||||
eol = "\n";
|
||||
|
||||
build_comparison (one, sleepy);
|
||||
g_data_input_stream_read_line_async (data, 0, NULL, asynch_ready, NULL);
|
||||
g_main_loop_run (loop = g_main_loop_new (NULL, FALSE));
|
||||
|
||||
g_assert_cmpstr (one->str, ==, two->str);
|
||||
g_string_free (one, TRUE);
|
||||
g_string_free (two, TRUE);
|
||||
g_object_unref (sleepy);
|
||||
g_object_unref (data);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||
|
||||
g_type_init ();
|
||||
g_test_add_func ("/filter-stream/input", test);
|
||||
g_test_add_func ("/filter-stream/async", asynch);
|
||||
|
||||
return g_test_run();
|
||||
}
|
298
gio/tests/socket-client.c
Normal file
298
gio/tests/socket-client.c
Normal file
@@ -0,0 +1,298 @@
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
GMainLoop *loop;
|
||||
|
||||
gboolean verbose = FALSE;
|
||||
gboolean non_blocking = FALSE;
|
||||
gboolean use_udp = FALSE;
|
||||
gboolean use_source = FALSE;
|
||||
int cancel_timeout = 0;
|
||||
|
||||
static GOptionEntry cmd_entries[] = {
|
||||
{"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
|
||||
"Cancel any op after the specified amount of seconds", NULL},
|
||||
{"udp", 'u', 0, G_OPTION_ARG_NONE, &use_udp,
|
||||
"Use udp instead of tcp", NULL},
|
||||
{"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
|
||||
"Be verbose", NULL},
|
||||
{"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
|
||||
"Enable non-blocking i/o", NULL},
|
||||
{"use-source", 's', 0, G_OPTION_ARG_NONE, &use_source,
|
||||
"Use GSource to wait for non-blocking i/o", NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static char *
|
||||
socket_address_to_string (GSocketAddress *address)
|
||||
{
|
||||
GInetAddress *inet_address;
|
||||
char *str, *res;
|
||||
int port;
|
||||
|
||||
inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
|
||||
str = g_inet_address_to_string (inet_address);
|
||||
port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
|
||||
res = g_strdup_printf ("%s:%d", str, port);
|
||||
g_free (str);
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
source_ready (gpointer data,
|
||||
GIOCondition condition)
|
||||
{
|
||||
g_main_loop_quit (loop);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_condition (GSocket *socket,
|
||||
const char *where,
|
||||
GCancellable *cancellable,
|
||||
GIOCondition condition)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GSource *source;
|
||||
|
||||
if (!non_blocking)
|
||||
return;
|
||||
|
||||
if (use_source)
|
||||
{
|
||||
source = g_socket_create_source (socket,
|
||||
condition,
|
||||
cancellable);
|
||||
g_source_set_callback (source,
|
||||
(GSourceFunc) source_ready,
|
||||
NULL, NULL);
|
||||
g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
g_main_loop_run (loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!g_socket_condition_wait (socket, condition, cancellable, &error))
|
||||
{
|
||||
g_printerr ("condition wait error for %s: %s\n",
|
||||
where,
|
||||
error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
cancel_thread (gpointer data)
|
||||
{
|
||||
GCancellable *cancellable = data;
|
||||
|
||||
g_usleep (1000*1000*cancel_timeout);
|
||||
g_print ("Cancelling\n");
|
||||
g_cancellable_cancel (cancellable);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
GSocket *socket;
|
||||
GSocketAddress *src_address;
|
||||
GSocketAddress *address;
|
||||
GSocketType socket_type;
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
GCancellable *cancellable;
|
||||
GSocketAddressEnumerator *enumerator;
|
||||
GSocketConnectable *connectable;
|
||||
|
||||
g_thread_init (NULL);
|
||||
|
||||
g_type_init ();
|
||||
|
||||
context = g_option_context_new (" <hostname>[:port] - Test GSocket client stuff");
|
||||
g_option_context_add_main_entries (context, cmd_entries, NULL);
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error))
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], "Need to specify hostname");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cancel_timeout)
|
||||
{
|
||||
cancellable = g_cancellable_new ();
|
||||
g_thread_create (cancel_thread, cancellable, FALSE, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
cancellable = NULL;
|
||||
}
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
if (use_udp)
|
||||
socket_type = G_SOCKET_TYPE_DATAGRAM;
|
||||
else
|
||||
socket_type = G_SOCKET_TYPE_STREAM;
|
||||
|
||||
socket = g_socket_new (G_SOCKET_FAMILY_IPV4, socket_type, 0, &error);
|
||||
if (socket == NULL)
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
connectable = g_network_address_parse (argv[1], 7777, &error);
|
||||
if (connectable == NULL)
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
enumerator = g_socket_connectable_enumerate (connectable);
|
||||
while (TRUE)
|
||||
{
|
||||
address = g_socket_address_enumerator_next (enumerator, cancellable, &error);
|
||||
if (address == NULL)
|
||||
{
|
||||
if (error == NULL)
|
||||
g_printerr ("%s: No more addresses to try\n", argv[0]);
|
||||
else
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_socket_connect (socket, address, cancellable, &error))
|
||||
break;
|
||||
g_printerr ("%s: Connection to %s failed: %s, trying next\n", argv[0], socket_address_to_string (address), error->message);
|
||||
g_error_free (error);
|
||||
error = NULL;
|
||||
|
||||
g_object_unref (address);
|
||||
}
|
||||
g_object_unref (enumerator);
|
||||
|
||||
g_print ("Connected to %s\n",
|
||||
socket_address_to_string (address));
|
||||
|
||||
/* TODO: Test non-blocking connect */
|
||||
if (non_blocking)
|
||||
g_socket_set_blocking (socket, FALSE);
|
||||
|
||||
src_address = g_socket_get_local_address (socket, &error);
|
||||
if (!src_address)
|
||||
{
|
||||
g_printerr ("Error getting local address: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
g_print ("local address: %s\n",
|
||||
socket_address_to_string (src_address));
|
||||
g_object_unref (src_address);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
gchar buffer[4096] = { };
|
||||
gssize size;
|
||||
gsize to_send;
|
||||
|
||||
if (fgets (buffer, sizeof buffer, stdin) == NULL)
|
||||
break;
|
||||
|
||||
to_send = strlen (buffer);
|
||||
while (to_send > 0)
|
||||
{
|
||||
ensure_condition (socket, "send", cancellable, G_IO_OUT);
|
||||
if (use_udp)
|
||||
size = g_socket_send_to (socket, address,
|
||||
buffer, to_send,
|
||||
cancellable, &error);
|
||||
else
|
||||
size = g_socket_send (socket, buffer, to_send,
|
||||
cancellable, &error);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
if (g_error_matches (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_WOULD_BLOCK))
|
||||
{
|
||||
g_print ("socket send would block, handling\n");
|
||||
g_error_free (error);
|
||||
error = NULL;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("Error sending to socket: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
g_print ("sent %" G_GSSIZE_FORMAT " bytes of data\n", size);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
g_printerr ("Unexpected short write\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
to_send -= size;
|
||||
}
|
||||
|
||||
ensure_condition (socket, "receive", cancellable, G_IO_IN);
|
||||
if (use_udp)
|
||||
size = g_socket_receive_from (socket, &src_address,
|
||||
buffer, sizeof buffer,
|
||||
cancellable, &error);
|
||||
else
|
||||
size = g_socket_receive (socket, buffer, sizeof buffer,
|
||||
cancellable, &error);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
g_printerr ("Error receiving from socket: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
break;
|
||||
|
||||
g_print ("received %" G_GSSIZE_FORMAT " bytes of data", size);
|
||||
if (use_udp)
|
||||
g_print (" from %s", socket_address_to_string (src_address));
|
||||
g_print ("\n");
|
||||
|
||||
if (verbose)
|
||||
g_print ("-------------------------\n"
|
||||
"%.*s"
|
||||
"-------------------------\n",
|
||||
(int)size, buffer);
|
||||
|
||||
}
|
||||
|
||||
g_print ("closing socket\n");
|
||||
|
||||
if (!g_socket_close (socket, &error))
|
||||
{
|
||||
g_printerr ("Error closing master socket: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (socket));
|
||||
|
||||
return 0;
|
||||
}
|
308
gio/tests/socket-server.c
Normal file
308
gio/tests/socket-server.c
Normal file
@@ -0,0 +1,308 @@
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
GMainLoop *loop;
|
||||
|
||||
int port = 7777;
|
||||
gboolean verbose = FALSE;
|
||||
gboolean dont_reuse_address = FALSE;
|
||||
gboolean non_blocking = FALSE;
|
||||
gboolean use_udp = FALSE;
|
||||
gboolean use_source = FALSE;
|
||||
int cancel_timeout = 0;
|
||||
|
||||
static GOptionEntry cmd_entries[] = {
|
||||
{"port", 'p', 0, G_OPTION_ARG_INT, &port,
|
||||
"Local port to bind to", NULL},
|
||||
{"cancel", 'c', 0, G_OPTION_ARG_INT, &cancel_timeout,
|
||||
"Cancel any op after the specified amount of seconds", NULL},
|
||||
{"udp", 'u', 0, G_OPTION_ARG_NONE, &use_udp,
|
||||
"Use udp instead of tcp", NULL},
|
||||
{"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
|
||||
"Be verbose", NULL},
|
||||
{"no-reuse", 0, 0, G_OPTION_ARG_NONE, &dont_reuse_address,
|
||||
"Don't SOADDRREUSE", NULL},
|
||||
{"non-blocking", 'n', 0, G_OPTION_ARG_NONE, &non_blocking,
|
||||
"Enable non-blocking i/o", NULL},
|
||||
{"use-source", 's', 0, G_OPTION_ARG_NONE, &use_source,
|
||||
"Use GSource to wait for non-blocking i/o", NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static char *
|
||||
socket_address_to_string (GSocketAddress *address)
|
||||
{
|
||||
GInetAddress *inet_address;
|
||||
char *str, *res;
|
||||
int the_port;
|
||||
|
||||
inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
|
||||
str = g_inet_address_to_string (inet_address);
|
||||
the_port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
|
||||
res = g_strdup_printf ("%s:%d", str, the_port);
|
||||
g_free (str);
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
source_ready (gpointer data,
|
||||
GIOCondition condition)
|
||||
{
|
||||
g_main_loop_quit (loop);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_condition (GSocket *socket,
|
||||
const char *where,
|
||||
GCancellable *cancellable,
|
||||
GIOCondition condition)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GSource *source;
|
||||
|
||||
if (!non_blocking)
|
||||
return;
|
||||
|
||||
if (use_source)
|
||||
{
|
||||
source = g_socket_create_source (socket,
|
||||
condition,
|
||||
cancellable);
|
||||
g_source_set_callback (source,
|
||||
(GSourceFunc) source_ready,
|
||||
NULL, NULL);
|
||||
g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
g_main_loop_run (loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!g_socket_condition_wait (socket, condition, cancellable, &error))
|
||||
{
|
||||
g_printerr ("condition wait error for %s: %s\n",
|
||||
where,
|
||||
error->message);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
cancel_thread (gpointer data)
|
||||
{
|
||||
GCancellable *cancellable = data;
|
||||
|
||||
g_usleep (1000*1000*cancel_timeout);
|
||||
g_print ("Cancelling\n");
|
||||
g_cancellable_cancel (cancellable);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
GSocket *socket, *new_socket, *recv_socket;
|
||||
GSocketAddress *src_address;
|
||||
GSocketAddress *address;
|
||||
GSocketType socket_type;
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
GCancellable *cancellable;
|
||||
|
||||
g_thread_init (NULL);
|
||||
|
||||
g_type_init ();
|
||||
|
||||
context = g_option_context_new (" - Test GSocket server stuff");
|
||||
g_option_context_add_main_entries (context, cmd_entries, NULL);
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error))
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cancel_timeout)
|
||||
{
|
||||
cancellable = g_cancellable_new ();
|
||||
g_thread_create (cancel_thread, cancellable, FALSE, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
cancellable = NULL;
|
||||
}
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
if (use_udp)
|
||||
socket_type = G_SOCKET_TYPE_DATAGRAM;
|
||||
else
|
||||
socket_type = G_SOCKET_TYPE_STREAM;
|
||||
|
||||
socket = g_socket_new (G_SOCKET_FAMILY_IPV4, socket_type, 0, &error);
|
||||
|
||||
if (socket == NULL)
|
||||
{
|
||||
g_printerr ("%s: %s\n", argv[0], error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (non_blocking)
|
||||
g_socket_set_blocking (socket, FALSE);
|
||||
|
||||
src_address = g_inet_socket_address_new (g_inet_address_new_any (G_SOCKET_FAMILY_IPV4), port);
|
||||
if (!g_socket_bind (socket, src_address, !dont_reuse_address, &error))
|
||||
{
|
||||
g_printerr ("Can't bind socket: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!use_udp)
|
||||
{
|
||||
if (!g_socket_listen (socket, &error))
|
||||
{
|
||||
g_printerr ("Can't listen on socket: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_print ("listening on port %d...\n", port);
|
||||
|
||||
ensure_condition (socket, "accept", cancellable, G_IO_IN);
|
||||
new_socket = g_socket_accept (socket, cancellable, &error);
|
||||
if (!new_socket)
|
||||
{
|
||||
g_printerr ("Error accepting socket: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (non_blocking)
|
||||
g_socket_set_blocking (new_socket, FALSE);
|
||||
|
||||
address = g_socket_get_remote_address (new_socket, &error);
|
||||
if (!address)
|
||||
{
|
||||
g_printerr ("Error getting remote address: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_print ("got a new connection from %s\n",
|
||||
socket_address_to_string (address));
|
||||
g_object_unref (address);
|
||||
|
||||
recv_socket = new_socket;
|
||||
}
|
||||
else
|
||||
{
|
||||
recv_socket = socket;
|
||||
new_socket = NULL;
|
||||
}
|
||||
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
gchar buffer[4096] = { };
|
||||
gssize size;
|
||||
gsize to_send;
|
||||
|
||||
ensure_condition (recv_socket, "receive", cancellable, G_IO_IN);
|
||||
if (use_udp)
|
||||
size = g_socket_receive_from (recv_socket, &address,
|
||||
buffer, sizeof buffer,
|
||||
cancellable, &error);
|
||||
else
|
||||
size = g_socket_receive (recv_socket, buffer, sizeof buffer,
|
||||
cancellable, &error);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
g_printerr ("Error receiving from socket: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
break;
|
||||
|
||||
g_print ("received %" G_GSSIZE_FORMAT " bytes of data", size);
|
||||
if (use_udp)
|
||||
g_print (" from %s", socket_address_to_string (address));
|
||||
g_print ("\n");
|
||||
|
||||
if (verbose)
|
||||
g_print ("-------------------------\n"
|
||||
"%.*s\n"
|
||||
"-------------------------\n",
|
||||
(int)size, buffer);
|
||||
|
||||
to_send = size;
|
||||
|
||||
while (to_send > 0)
|
||||
{
|
||||
ensure_condition (recv_socket, "send", cancellable, G_IO_OUT);
|
||||
if (use_udp)
|
||||
size = g_socket_send_to (recv_socket, address,
|
||||
buffer, to_send, cancellable, &error);
|
||||
else
|
||||
size = g_socket_send (recv_socket, buffer, to_send,
|
||||
cancellable, &error);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
if (g_error_matches (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_WOULD_BLOCK))
|
||||
{
|
||||
g_print ("socket send would block, handling\n");
|
||||
g_error_free (error);
|
||||
error = NULL;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("Error sending to socket: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
g_print ("sent %" G_GSSIZE_FORMAT " bytes of data\n", size);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
g_printerr ("Unexpected short write\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
to_send -= size;
|
||||
}
|
||||
}
|
||||
|
||||
g_print ("connection closed\n");
|
||||
|
||||
if (new_socket)
|
||||
{
|
||||
if (!g_socket_close (new_socket, &error))
|
||||
{
|
||||
g_printerr ("Error closing connection socket: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (new_socket));
|
||||
}
|
||||
|
||||
if (!g_socket_close (socket, &error))
|
||||
{
|
||||
g_printerr ("Error closing master socket: %s\n",
|
||||
error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (socket));
|
||||
|
||||
return 0;
|
||||
}
|
158
gio/tests/srvtarget.c
Normal file
158
gio/tests/srvtarget.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NUM_TRIALS 250000
|
||||
|
||||
struct {
|
||||
const char *order;
|
||||
int expected, seen;
|
||||
} ordering[] = {
|
||||
/* There are 32 legitimate orderings; the result always has to start
|
||||
* with either "fe" (usually) or "ef" (rarely). For the remaining
|
||||
* letters, "cbda" is the most likely, with various other orders
|
||||
* possible, down to "adbc" being the most improbable. However,
|
||||
* almost all "fe" orderings are more likely than almost any "ef"
|
||||
* orderings. The complete probability ordering, from most-likely
|
||||
* to least-likely is something roughly like:
|
||||
*/
|
||||
{ "fecbda", 0.2468 * NUM_TRIALS, 0},
|
||||
{ "febcda", 0.1885 * NUM_TRIALS, 0},
|
||||
{ "fecdba", 0.1346 * NUM_TRIALS, 0},
|
||||
{ "fedcba", 0.0830 * NUM_TRIALS, 0},
|
||||
{ "febdca", 0.0706 * NUM_TRIALS, 0},
|
||||
{ "fedbca", 0.0571 * NUM_TRIALS, 0},
|
||||
{ "fecbad", 0.0496 * NUM_TRIALS, 0},
|
||||
{ "febcad", 0.0374 * NUM_TRIALS, 0},
|
||||
{ "fecabd", 0.0185 * NUM_TRIALS, 0},
|
||||
{ "fecdab", 0.0136 * NUM_TRIALS, 0},
|
||||
{ "fecadb", 0.0110 * NUM_TRIALS, 0},
|
||||
{ "febacd", 0.0108 * NUM_TRIALS, 0},
|
||||
{ "feacbd", 0.0096 * NUM_TRIALS, 0},
|
||||
{ "fedcab", 0.0083 * NUM_TRIALS, 0},
|
||||
{ "feabcd", 0.0073 * NUM_TRIALS, 0},
|
||||
{ "feacdb", 0.0058 * NUM_TRIALS, 0},
|
||||
{ "efcbda", 0.0049 * NUM_TRIALS, 0},
|
||||
{ "febdac", 0.0048 * NUM_TRIALS, 0},
|
||||
{ "febadc", 0.0043 * NUM_TRIALS, 0},
|
||||
{ "fedbac", 0.0038 * NUM_TRIALS, 0},
|
||||
{ "efbcda", 0.0038 * NUM_TRIALS, 0},
|
||||
{ "feadcb", 0.0036 * NUM_TRIALS, 0},
|
||||
{ "fedacb", 0.0035 * NUM_TRIALS, 0},
|
||||
{ "feabdc", 0.0029 * NUM_TRIALS, 0},
|
||||
{ "feadbc", 0.0026 * NUM_TRIALS, 0},
|
||||
{ "fedabc", 0.0026 * NUM_TRIALS, 0},
|
||||
{ "efcdba", 0.0026 * NUM_TRIALS, 0},
|
||||
{ "efdcba", 0.0017 * NUM_TRIALS, 0},
|
||||
{ "efbdca", 0.0014 * NUM_TRIALS, 0},
|
||||
{ "efdbca", 0.0011 * NUM_TRIALS, 0},
|
||||
{ "efcbad", 0.0010 * NUM_TRIALS, 0},
|
||||
{ "efbcad", 0.0008 * NUM_TRIALS, 0},
|
||||
{ "efcabd", 0.0004 * NUM_TRIALS, 0},
|
||||
{ "efcdab", 0.0003 * NUM_TRIALS, 0},
|
||||
{ "efcadb", 0.0002 * NUM_TRIALS, 0},
|
||||
{ "efbacd", 0.0002 * NUM_TRIALS, 0},
|
||||
{ "efacbd", 0.0002 * NUM_TRIALS, 0},
|
||||
{ "efdcab", 0.0002 * NUM_TRIALS, 0},
|
||||
{ "efabcd", 0.0002 * NUM_TRIALS, 0},
|
||||
{ "efacdb", 0.0001 * NUM_TRIALS, 0},
|
||||
{ "efbdac", 0.0001 * NUM_TRIALS, 0},
|
||||
{ "efadcb", 0.0001 * NUM_TRIALS, 0},
|
||||
{ "efdbac", 0.0001 * NUM_TRIALS, 0},
|
||||
{ "efbadc", 0.0001 * NUM_TRIALS, 0},
|
||||
{ "efdacb", 0.0001 * NUM_TRIALS, 0},
|
||||
{ "efabdc", 0.0001 * NUM_TRIALS, 0},
|
||||
{ "efadbc", 0.00005 * NUM_TRIALS, 0},
|
||||
{ "efdabc", 0.00005 * NUM_TRIALS, 0}
|
||||
};
|
||||
#define NUM_ORDERINGS G_N_ELEMENTS (ordering)
|
||||
|
||||
static void
|
||||
test_srv_target_ordering (void)
|
||||
{
|
||||
GList *targets, *sorted, *t;
|
||||
char result[7], *p;
|
||||
int i;
|
||||
guint o;
|
||||
|
||||
targets = NULL;
|
||||
/* name, port, priority, weight */
|
||||
targets = g_list_append (targets, g_srv_target_new ("a", 0, 2, 0));
|
||||
targets = g_list_append (targets, g_srv_target_new ("b", 0, 2, 10));
|
||||
targets = g_list_append (targets, g_srv_target_new ("c", 0, 2, 15));
|
||||
targets = g_list_append (targets, g_srv_target_new ("d", 0, 2, 5));
|
||||
targets = g_list_append (targets, g_srv_target_new ("e", 0, 1, 0));
|
||||
targets = g_list_append (targets, g_srv_target_new ("f", 0, 1, 50));
|
||||
|
||||
for (i = 0; i < NUM_TRIALS; i++)
|
||||
{
|
||||
g_random_set_seed (i);
|
||||
|
||||
sorted = g_srv_target_list_sort (g_list_copy (targets));
|
||||
|
||||
for (t = sorted, p = result; t; t = t->next)
|
||||
*(p++) = *g_srv_target_get_hostname (t->data);
|
||||
*p = '\0';
|
||||
g_list_free (sorted);
|
||||
|
||||
for (o = 0; o < NUM_ORDERINGS; o++)
|
||||
{
|
||||
if (!strcmp (result, ordering[o].order))
|
||||
{
|
||||
ordering[o].seen++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assert that @result matched one of the valid orderings */
|
||||
if (o == NUM_ORDERINGS)
|
||||
{
|
||||
char *msg = g_strdup_printf ("result '%s' is invalid", result);
|
||||
g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assert that each ordering appeared roughly the expected
|
||||
* number of times.
|
||||
*/
|
||||
for (o = 0; o < NUM_ORDERINGS; o++)
|
||||
{
|
||||
g_assert_cmpint (ordering[o].seen, >, ordering[o].expected / 2);
|
||||
g_assert_cmpint (ordering[o].seen, <, ordering[o].expected * 2);
|
||||
}
|
||||
|
||||
g_resolver_free_targets (targets);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/srvtarget/srv-target-ordering", test_srv_target_ordering);
|
||||
|
||||
return g_test_run();
|
||||
}
|
256
gio/tests/unix-streams.c
Normal file
256
gio/tests/unix-streams.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/* GLib testing framework examples and tests
|
||||
* Copyright (C) 2008 Red Hat, Inc
|
||||
*
|
||||
* This work is provided "as is"; redistribution and modification
|
||||
* in whole or in part, in any medium, physical or electronic is
|
||||
* permitted without restriction.
|
||||
*
|
||||
* This work 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.
|
||||
*
|
||||
* In no event shall the authors or contributors be liable for any
|
||||
* direct, indirect, incidental, special, exemplary, or consequential
|
||||
* damages (including, but not limited to, procurement of substitute
|
||||
* goods or services; loss of use, data, or profits; or business
|
||||
* interruption) however caused and on any theory of liability, whether
|
||||
* in contract, strict liability, or tort (including negligence or
|
||||
* otherwise) arising in any way out of the use of this software, even
|
||||
* if advised of the possibility of such damage.
|
||||
*/
|
||||
|
||||
#include <glib/glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gunixinputstream.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DATA "abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
int writer_pipe[2], reader_pipe[2];
|
||||
GCancellable *writer_cancel, *reader_cancel, *main_cancel;
|
||||
GMainLoop *loop;
|
||||
|
||||
static gpointer
|
||||
writer_thread (gpointer user_data)
|
||||
{
|
||||
GOutputStream *out;
|
||||
gssize nwrote, offset;
|
||||
GError *err = NULL;
|
||||
|
||||
out = g_unix_output_stream_new (writer_pipe[1], TRUE);
|
||||
|
||||
do
|
||||
{
|
||||
g_usleep (10);
|
||||
|
||||
offset = 0;
|
||||
while (offset < (gssize) sizeof (DATA))
|
||||
{
|
||||
nwrote = g_output_stream_write (out, DATA + offset,
|
||||
sizeof (DATA) - offset,
|
||||
writer_cancel, &err);
|
||||
if (nwrote <= 0 || err != NULL)
|
||||
break;
|
||||
offset += nwrote;
|
||||
}
|
||||
|
||||
g_assert (nwrote > 0 || err != NULL);
|
||||
}
|
||||
while (err == NULL);
|
||||
|
||||
if (g_cancellable_is_cancelled (writer_cancel))
|
||||
{
|
||||
g_cancellable_cancel (main_cancel);
|
||||
g_object_unref (out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_warning ("writer: %s", err->message);
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static gpointer
|
||||
reader_thread (gpointer user_data)
|
||||
{
|
||||
GInputStream *in;
|
||||
gssize nread, total;
|
||||
GError *err = NULL;
|
||||
char buf[sizeof (DATA)];
|
||||
|
||||
in = g_unix_input_stream_new (reader_pipe[0], TRUE);
|
||||
|
||||
do
|
||||
{
|
||||
total = 0;
|
||||
while (total < (gssize) sizeof (DATA))
|
||||
{
|
||||
nread = g_input_stream_read (in, buf + total, sizeof (buf) - total,
|
||||
reader_cancel, &err);
|
||||
if (nread <= 0 || err != NULL)
|
||||
break;
|
||||
total += nread;
|
||||
}
|
||||
|
||||
if (err)
|
||||
break;
|
||||
|
||||
if (nread == 0)
|
||||
{
|
||||
g_assert (err == NULL);
|
||||
/* pipe closed */
|
||||
g_object_unref (in);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_assert_cmpstr (buf, ==, DATA);
|
||||
g_assert (!g_cancellable_is_cancelled (reader_cancel));
|
||||
}
|
||||
while (err == NULL);
|
||||
|
||||
g_warning ("reader: %s", err->message);
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
char main_buf[sizeof (DATA)];
|
||||
gssize main_len, main_offset;
|
||||
|
||||
static void readable (GObject *source, GAsyncResult *res, gpointer user_data);
|
||||
static void writable (GObject *source, GAsyncResult *res, gpointer user_data);
|
||||
|
||||
static void
|
||||
do_main_cancel (GOutputStream *out)
|
||||
{
|
||||
g_output_stream_close (out, NULL, NULL);
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
readable (GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
GInputStream *in = G_INPUT_STREAM (source);
|
||||
GOutputStream *out = user_data;
|
||||
GError *err = NULL;
|
||||
|
||||
main_len = g_input_stream_read_finish (in, res, &err);
|
||||
|
||||
if (g_cancellable_is_cancelled (main_cancel))
|
||||
{
|
||||
do_main_cancel (out);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (err == NULL);
|
||||
|
||||
main_offset = 0;
|
||||
g_output_stream_write_async (out, main_buf, main_len,
|
||||
G_PRIORITY_DEFAULT, main_cancel,
|
||||
writable, in);
|
||||
}
|
||||
|
||||
static void
|
||||
writable (GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
GOutputStream *out = G_OUTPUT_STREAM (source);
|
||||
GInputStream *in = user_data;
|
||||
GError *err = NULL;
|
||||
gssize nwrote;
|
||||
|
||||
nwrote = g_output_stream_write_finish (out, res, &err);
|
||||
|
||||
if (g_cancellable_is_cancelled (main_cancel))
|
||||
{
|
||||
do_main_cancel (out);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (err == NULL);
|
||||
g_assert_cmpint (nwrote, <=, main_len - main_offset);
|
||||
|
||||
main_offset += nwrote;
|
||||
if (main_offset == main_len)
|
||||
{
|
||||
g_input_stream_read_async (in, main_buf, sizeof (main_buf),
|
||||
G_PRIORITY_DEFAULT, main_cancel,
|
||||
readable, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_output_stream_write_async (out, main_buf + main_offset,
|
||||
main_len - main_offset,
|
||||
G_PRIORITY_DEFAULT, main_cancel,
|
||||
writable, in);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout (gpointer cancellable)
|
||||
{
|
||||
g_cancellable_cancel (cancellable);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_pipe_io (void)
|
||||
{
|
||||
GThread *writer, *reader;
|
||||
GInputStream *in;
|
||||
GOutputStream *out;
|
||||
|
||||
/* Split off two (additional) threads, a reader and a writer. From
|
||||
* the writer thread, write data synchronously in small chunks,
|
||||
* which gets read asynchronously by the main thread and then
|
||||
* written asynchronously to the reader thread, which reads it
|
||||
* synchronously. Eventually a timeout in the main thread will cause
|
||||
* it to cancel the writer thread, which will in turn cancel the
|
||||
* read op in the main thread, which will then close the pipe to
|
||||
* the reader thread, causing the read op to fail.
|
||||
*/
|
||||
|
||||
g_assert (pipe (writer_pipe) == 0 && pipe (reader_pipe) == 0);
|
||||
|
||||
writer_cancel = g_cancellable_new ();
|
||||
reader_cancel = g_cancellable_new ();
|
||||
main_cancel = g_cancellable_new ();
|
||||
|
||||
writer = g_thread_create (writer_thread, NULL, TRUE, NULL);
|
||||
reader = g_thread_create (reader_thread, NULL, TRUE, NULL);
|
||||
|
||||
in = g_unix_input_stream_new (writer_pipe[0], TRUE);
|
||||
out = g_unix_output_stream_new (reader_pipe[1], TRUE);
|
||||
|
||||
g_input_stream_read_async (in, main_buf, sizeof (main_buf),
|
||||
G_PRIORITY_DEFAULT, main_cancel,
|
||||
readable, out);
|
||||
|
||||
g_timeout_add (500, timeout, writer_cancel);
|
||||
|
||||
loop = g_main_loop_new (NULL, TRUE);
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
|
||||
g_thread_join (reader);
|
||||
g_thread_join (writer);
|
||||
|
||||
g_object_unref (main_cancel);
|
||||
g_object_unref (reader_cancel);
|
||||
g_object_unref (writer_cancel);
|
||||
g_object_unref (in);
|
||||
g_object_unref (out);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_thread_init (NULL);
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/unix-streams/pipe-io-test", test_pipe_io);
|
||||
|
||||
return g_test_run();
|
||||
}
|
Reference in New Issue
Block a user