From 4c6c0b9099f55b22d6930444921db720a3655713 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 2 May 2021 09:17:20 -0400 Subject: [PATCH] Add a test for custom serializers --- testsuite/gdk/contentserializer.c | 288 ++++++++++++++++++++++++++---- 1 file changed, 249 insertions(+), 39 deletions(-) diff --git a/testsuite/gdk/contentserializer.c b/testsuite/gdk/contentserializer.c index c317531088..d20a60d99e 100644 --- a/testsuite/gdk/contentserializer.c +++ b/testsuite/gdk/contentserializer.c @@ -2,14 +2,69 @@ #include +typedef gboolean (* ValueCompareFunc) (GValue *v1, GValue *v2); + typedef struct { GOutputStream *ostream; GInputStream *istream; const char *mime_type; GValue value; + ValueCompareFunc compare; gboolean done; } TestData; +static gboolean +compare_string_values (GValue *v1, GValue *v2) +{ + return G_VALUE_TYPE (v1) == G_TYPE_STRING && + G_VALUE_TYPE (v2) == G_TYPE_STRING && + strcmp (g_value_get_string (v1), g_value_get_string (v2)) == 0; +} + +static gboolean +compare_rgba_values (GValue *v1, GValue *v2) +{ + return G_VALUE_TYPE (v1) == GDK_TYPE_RGBA && + G_VALUE_TYPE (v2) == GDK_TYPE_RGBA && + gdk_rgba_equal ((GdkRGBA *)g_value_get_boxed (v1), + (GdkRGBA *)g_value_get_boxed (v2)); +} + +static gboolean +compare_file_values (GValue *v1, GValue *v2) +{ + return G_VALUE_TYPE (v1) == G_TYPE_FILE && + G_VALUE_TYPE (v2) == G_TYPE_FILE && + g_file_equal ((GFile *)g_value_get_object (v1), + (GFile *)g_value_get_object (v2)); +} + +static gboolean +compare_file_list_values (GValue *v1, GValue *v2) +{ + GSList *s1, *s2, *l1, *l2; + + if (G_VALUE_TYPE (v1) != GDK_TYPE_FILE_LIST || + G_VALUE_TYPE (v2) != GDK_TYPE_FILE_LIST) + return FALSE; + + s1 = g_value_get_boxed (v1); + s2 = g_value_get_boxed (v2); + + if (g_slist_length (s1) != g_slist_length (s2)) + return FALSE; + + for (l1 = s1, l2 = s2; l1 != NULL; l1 = l1->next, l2 = l2->next) + { + GFile *f1 = l1->data; + GFile *f2 = l2->data; + if (!g_file_equal (f1, f2)) + return FALSE; + } + + return TRUE; +} + static void deserialize_done (GObject *source, GAsyncResult *result, @@ -26,38 +81,7 @@ deserialize_done (GObject *source, g_assert_true (res); g_assert_no_error (error); - if (G_VALUE_TYPE (&data->value) == G_TYPE_STRING) - g_assert_cmpstr (g_value_get_string (&data->value), ==, g_value_get_string (&value)); - else if (G_VALUE_TYPE (&data->value) == GDK_TYPE_RGBA) - { - GdkRGBA *c1 = g_value_get_boxed (&data->value); - GdkRGBA *c2 = g_value_get_boxed (&value); - - g_assert_true (gdk_rgba_equal (c1, c2)); - } - else if (G_VALUE_TYPE (&data->value) == G_TYPE_FILE) - { - GFile *f1 = g_value_get_object (&data->value); - GFile *f2 = g_value_get_object (&value); - - g_assert_true (g_file_equal (f1, f2)); - } - else if (G_VALUE_TYPE (&data->value) == GDK_TYPE_FILE_LIST) - { - GSList *s1 = g_value_get_boxed (&data->value); - GSList *s2 = g_value_get_boxed (&value); - GSList *l1, *l2; - - g_assert_cmpint (g_slist_length (s1), ==, g_slist_length (s2)); - for (l1 = s1, l2 = s2; l1 != NULL; l1 = l1->next, l2 = l2->next) - { - GFile *f1 = l1->data; - GFile *f2 = l2->data; - g_assert_true (g_file_equal (f1, f2)); - } - } - else - g_assert_not_reached (); + g_assert_true (data->compare (&data->value, &value)); g_value_unset (&value); @@ -94,8 +118,9 @@ serialize_done (GObject *source, } static void -test_content_roundtrip (const GValue *value, - const char *mime_type) +test_content_roundtrip (const GValue *value, + const char *mime_type, + ValueCompareFunc compare) { TestData data = { 0, }; @@ -103,6 +128,7 @@ test_content_roundtrip (const GValue *value, data.mime_type = g_strdup (mime_type); g_value_init (&data.value, G_VALUE_TYPE (value)); g_value_copy (value, &data.value); + data.compare = compare; data.done = FALSE; gdk_content_serialize_async (data.ostream, @@ -128,7 +154,7 @@ test_content_text_plain_utf8 (void) g_value_init (&value, G_TYPE_STRING); g_value_set_string (&value, "ABCDEF12345"); - test_content_roundtrip (&value, "text/plain;charset=utf-8"); + test_content_roundtrip (&value, "text/plain;charset=utf-8", compare_string_values); g_value_unset (&value); } @@ -139,7 +165,7 @@ test_content_text_plain (void) g_value_init (&value, G_TYPE_STRING); g_value_set_string (&value, "ABCDEF12345"); - test_content_roundtrip (&value, "text/plain"); + test_content_roundtrip (&value, "text/plain", compare_string_values); g_value_unset (&value); } @@ -152,7 +178,7 @@ test_content_color (void) gdk_rgba_parse (&color, "magenta"); g_value_init (&value, GDK_TYPE_RGBA); g_value_set_boxed (&value, &color); - test_content_roundtrip (&value, "application/x-color"); + test_content_roundtrip (&value, "application/x-color", compare_rgba_values); g_value_unset (&value); } @@ -165,7 +191,7 @@ test_content_file (void) file = g_file_new_for_path ("/etc/passwd"); g_value_init (&value, G_TYPE_FILE); g_value_set_object (&value, file); - test_content_roundtrip (&value, "text/uri-list"); + test_content_roundtrip (&value, "text/uri-list", compare_file_values); g_value_unset (&value); g_object_unref (file); } @@ -182,11 +208,194 @@ test_content_files (void) g_value_init (&value, GDK_TYPE_FILE_LIST); g_value_set_boxed (&value, files); - test_content_roundtrip (&value, "text/uri-list"); + test_content_roundtrip (&value, "text/uri-list", compare_file_list_values); g_value_unset (&value); g_slist_free_full (files, g_object_unref); } +#define MY_TYPE_INT_LIST (my_int_list_get_type ()) +GType my_int_list_get_type (void) G_GNUC_CONST; + +typedef gpointer MyIntList; + +static gpointer +my_int_list_copy (gpointer list) +{ + int size; + gpointer copy; + + size = *(int *)list; + copy = g_malloc ((size + 1) * sizeof (int)); + memcpy (copy, list, (size + 1) * sizeof (int)); + + return copy; +} + +static void +my_int_list_free (gpointer list) +{ + g_free (list); +} + +G_DEFINE_BOXED_TYPE (MyIntList, my_int_list, my_int_list_copy, my_int_list_free) + +static void +int_list_serializer_finish (GObject *source, + GAsyncResult *result, + gpointer serializer) +{ + GOutputStream *stream = G_OUTPUT_STREAM (source); + GError *error = NULL; + + if (!g_output_stream_write_all_finish (stream, result, NULL, &error)) + gdk_content_serializer_return_error (serializer, error); + else + gdk_content_serializer_return_success (serializer); +} + +static void +int_list_serializer (GdkContentSerializer *serializer) +{ + GString *str; + const GValue *value; + int *data; + + str = g_string_new (NULL); + value = gdk_content_serializer_get_value (serializer); + + data = g_value_get_boxed (value); + for (int i = 0; i < data[0] + 1; i++) + { + if (i > 0) + g_string_append_c (str, ' '); + g_string_append_printf (str, "%d", data[i]); + } + + g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer), + str->str, + str->len, + gdk_content_serializer_get_priority (serializer), + gdk_content_serializer_get_cancellable (serializer), + int_list_serializer_finish, + serializer); + gdk_content_serializer_set_task_data (serializer, g_string_free (str, FALSE), g_free); +} + +static void +int_list_deserializer_finish (GObject *source, + GAsyncResult *result, + gpointer deserializer) +{ + GOutputStream *stream = G_OUTPUT_STREAM (source); + GError *error = NULL; + gssize written; + GValue *value; + char *str; + char **strv; + int size; + int *data; + + written = g_output_stream_splice_finish (stream, result, &error); + if (written < 0) + { + gdk_content_deserializer_return_error (deserializer, error); + return; + } + + /* write terminating NULL */ + if (g_output_stream_write (stream, "", 1, NULL, &error) < 0 || + !g_output_stream_close (stream, NULL, &error)) + { + gdk_content_deserializer_return_error (deserializer, error); + return; + } + + str = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (stream)); + strv = g_strsplit (str, " ", -1); + size = atoi (strv[0]); + if (size + 1 != g_strv_length (strv)) + { + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, "Int list corrupt"); + gdk_content_deserializer_return_error (deserializer, error); + g_free (str); + g_strfreev (strv); + return; + } + + data = g_malloc ((size + 1) * sizeof (int)); + for (int i = 0; i < size + 1; i++) + data[i] = atoi (strv[i]); + g_free (str); + g_strfreev (strv); + + value = gdk_content_deserializer_get_value (deserializer); + g_value_take_boxed (value, data); + + gdk_content_deserializer_return_success (deserializer); +} + +static void +int_list_deserializer (GdkContentDeserializer *deserializer) +{ + GOutputStream *output; + + output = g_memory_output_stream_new_resizable (); + + g_output_stream_splice_async (output, + gdk_content_deserializer_get_input_stream (deserializer), + G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, + gdk_content_deserializer_get_priority (deserializer), + gdk_content_deserializer_get_cancellable (deserializer), + int_list_deserializer_finish, + deserializer); + g_object_unref (output); +} + +static gboolean +compare_int_list_values (GValue *v1, GValue *v2) +{ + int *d1, *d2; + + if (G_VALUE_TYPE (v1) != MY_TYPE_INT_LIST || + G_VALUE_TYPE (v2) != MY_TYPE_INT_LIST) + return FALSE; + + d1 = g_value_get_boxed (v1); + d2 = g_value_get_boxed (v2); + + if (d1[0] != d2[0]) + return FALSE; + + return memcmp (d1, d2, (d1[0] + 1) * sizeof (int)) == 0; +} + +static void +test_custom_format (void) +{ + int *data; + GValue value = G_VALUE_INIT; + + gdk_content_register_serializer (MY_TYPE_INT_LIST, + "application/x-int-list", + int_list_serializer, + NULL, NULL); + gdk_content_register_deserializer ("application/x-int-list", + MY_TYPE_INT_LIST, + int_list_deserializer, + NULL, NULL); + + data = g_malloc (3 * sizeof (int)); + data[0] = 2; + data[1] = 3; + data[2] = 5; + + g_value_init (&value, MY_TYPE_INT_LIST); + g_value_set_boxed (&value, data); + test_content_roundtrip (&value, "application/x-int-list", compare_int_list_values); + g_value_unset (&value); + g_free (data); +} + int main (int argc, char *argv[]) { @@ -199,6 +408,7 @@ main (int argc, char *argv[]) g_test_add_func ("/content/color", test_content_color); g_test_add_func ("/content/file", test_content_file); g_test_add_func ("/content/files", test_content_files); + g_test_add_func ("/content/custom", test_custom_format); return g_test_run (); }