[glib: 11/15] Add some tests for g_output_stream_writev() and its async variant



commit 708aa8f4eee119a6dd542904ab962030a9337993
Author: Sebastian Dröge <sebastian centricular com>
Date:   Fri Sep 14 12:54:00 2018 +0300

    Add some tests for g_output_stream_writev() and its async variant

 gio/tests/file.c                 | 567 +++++++++++++++++++++++++++++++++++++++
 gio/tests/memory-output-stream.c |  90 +++++++
 2 files changed, 657 insertions(+)
---
diff --git a/gio/tests/file.c b/gio/tests/file.c
index d2f147419..affa0bce6 100644
--- a/gio/tests/file.c
+++ b/gio/tests/file.c
@@ -1162,6 +1162,562 @@ test_load_bytes_async (void)
   g_main_loop_unref (data.main_loop);
 }
 
+static void
+test_writev_helper (GOutputVector *vectors,
+                    gsize          n_vectors,
+                    gboolean       use_bytes_written,
+                    const guint8  *expected_contents,
+                    gsize          expected_length)
+{
+  GFile *file;
+  GFileIOStream *iostream = NULL;
+  GOutputStream *ostream;
+  GError *error = NULL;
+  gsize bytes_written = 0;
+  gboolean res;
+  guint8 *contents;
+  gsize length;
+
+  file = g_file_new_tmp ("g_file_writev_XXXXXX",
+                         &iostream, NULL);
+  g_assert_nonnull (file);
+  g_assert_nonnull (iostream);
+
+  ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+  res = g_output_stream_writev_all (ostream, vectors, n_vectors, use_bytes_written ? &bytes_written : NULL, 
NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  if (use_bytes_written)
+    g_assert_cmpuint (bytes_written, ==, expected_length);
+
+  res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_object_unref (iostream);
+
+  res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+
+  g_assert_cmpmem (contents, length, expected_contents, expected_length);
+
+  g_free (contents);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
+/* Test that writev() on local file output streams works on a non-empty vector */
+static void
+test_writev (void)
+{
+  GOutputVector vectors[3];
+  const guint8 buffer[] = {1, 2, 3, 4, 5,
+                           1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+                           1, 2, 3};
+
+  vectors[0].buffer = buffer;
+  vectors[0].size = 5;
+
+  vectors[1].buffer = buffer + 5;
+  vectors[1].size = 12;
+
+  vectors[2].buffer = buffer + 5 + 12;
+  vectors[2].size = 3;
+
+  test_writev_helper (vectors, G_N_ELEMENTS (vectors), TRUE, buffer, sizeof buffer);
+}
+
+/* Test that writev() on local file output streams works on a non-empty vector without returning 
bytes_written */
+static void
+test_writev_no_bytes_written (void)
+{
+  GOutputVector vectors[3];
+  const guint8 buffer[] = {1, 2, 3, 4, 5,
+                           1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+                           1, 2, 3};
+
+  vectors[0].buffer = buffer;
+  vectors[0].size = 5;
+
+  vectors[1].buffer = buffer + 5;
+  vectors[1].size = 12;
+
+  vectors[2].buffer = buffer + 5 + 12;
+  vectors[2].size = 3;
+
+  test_writev_helper (vectors, G_N_ELEMENTS (vectors), FALSE, buffer, sizeof buffer);
+}
+
+/* Test that writev() on local file output streams works on 0 vectors */
+static void
+test_writev_no_vectors (void)
+{
+  test_writev_helper (NULL, 0, TRUE, NULL, 0);
+}
+
+/* Test that writev() on local file output streams works on empty vectors */
+static void
+test_writev_empty_vectors (void)
+{
+  GOutputVector vectors[3];
+
+  vectors[0].buffer = NULL;
+  vectors[0].size = 0;
+  vectors[1].buffer = NULL;
+  vectors[1].size = 0;
+  vectors[2].buffer = NULL;
+  vectors[2].size = 0;
+
+  test_writev_helper (vectors, G_N_ELEMENTS (vectors), TRUE, NULL, 0);
+}
+
+/* Test that writev() fails if the sum of sizes in the vector is too big */
+static void
+test_writev_too_big_vectors (void)
+{
+  GFile *file;
+  GFileIOStream *iostream = NULL;
+  GOutputStream *ostream;
+  GError *error = NULL;
+  gsize bytes_written = 0;
+  gboolean res;
+  guint8 *contents;
+  gsize length;
+  GOutputVector vectors[3];
+
+  vectors[0].buffer = (void*) 1;
+  vectors[0].size = G_MAXSIZE / 2;
+
+  vectors[1].buffer = (void*) 1;
+  vectors[1].size = G_MAXSIZE / 2;
+
+  vectors[2].buffer = (void*) 1;
+  vectors[2].size = G_MAXSIZE / 2;
+
+  file = g_file_new_tmp ("g_file_writev_XXXXXX",
+                         &iostream, NULL);
+  g_assert_nonnull (file);
+  g_assert_nonnull (iostream);
+
+  ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+  res = g_output_stream_writev_all (ostream, vectors, G_N_ELEMENTS (vectors), &bytes_written, NULL, &error);
+  g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
+  g_assert_cmpuint (bytes_written, ==, 0);
+  g_assert_false (res);
+  g_clear_error (&error);
+
+  res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_object_unref (iostream);
+
+  res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+
+  g_assert_cmpmem (contents, length, NULL, 0);
+
+  g_free (contents);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
+typedef struct
+{
+  gsize bytes_written;
+  GOutputVector *vectors;
+  gsize n_vectors;
+  GError *error;
+  gboolean done;
+} WritevAsyncData;
+
+static void
+test_writev_async_cb (GObject      *object,
+                      GAsyncResult *result,
+                      gpointer      user_data)
+{
+  GOutputStream *ostream = G_OUTPUT_STREAM (object);
+  WritevAsyncData *data = user_data;
+  GError *error = NULL;
+  gsize bytes_written;
+  gboolean res;
+
+  res = g_output_stream_writev_finish (ostream, result, &bytes_written, &error);
+  g_assert_true (res);
+  g_assert_no_error (error);
+  data->bytes_written += bytes_written;
+
+  /* skip vectors that have been written in full */
+  while (data->n_vectors > 0 && bytes_written >= data->vectors[0].size)
+    {
+      bytes_written -= data->vectors[0].size;
+      ++data->vectors;
+      --data->n_vectors;
+    }
+  /* skip partially written vector data */
+  if (bytes_written > 0 && data->n_vectors > 0)
+    {
+      data->vectors[0].size -= bytes_written;
+      data->vectors[0].buffer = ((guint8 *) data->vectors[0].buffer) + bytes_written;
+    }
+
+  if (data->n_vectors > 0)
+    g_output_stream_writev_async (ostream, data->vectors, data->n_vectors, 0, NULL, test_writev_async_cb, 
&data);
+}
+
+/* Test that writev_async() on local file output streams works on a non-empty vector */
+static void
+test_writev_async (void)
+{
+  WritevAsyncData data = { 0 };
+  GFile *file;
+  GFileIOStream *iostream = NULL;
+  GOutputVector vectors[3];
+  const guint8 buffer[] = {1, 2, 3, 4, 5,
+                           1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+                           1, 2, 3};
+  GOutputStream *ostream;
+  GError *error = NULL;
+  gboolean res;
+  guint8 *contents;
+  gsize length;
+
+  vectors[0].buffer = buffer;
+  vectors[0].size = 5;
+
+  vectors[1].buffer = buffer + 5;
+  vectors[1].size = 12;
+
+  vectors[2].buffer = buffer + 5  + 12;
+  vectors[2].size = 3;
+
+  file = g_file_new_tmp ("g_file_writev_XXXXXX",
+                         &iostream, NULL);
+  g_assert_nonnull (file);
+  g_assert_nonnull (iostream);
+
+  data.vectors = vectors;
+  data.n_vectors = G_N_ELEMENTS (vectors);
+
+  ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+  g_output_stream_writev_async (ostream, data.vectors, data.n_vectors, 0, NULL, test_writev_async_cb, &data);
+
+  while (data.n_vectors > 0)
+    g_main_context_iteration (NULL, TRUE);
+
+  g_assert_cmpuint (data.bytes_written, ==, sizeof buffer);
+
+  res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_object_unref (iostream);
+
+  res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+
+  g_assert_cmpmem (contents, length, buffer, sizeof buffer);
+
+  g_free (contents);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
+static void
+test_writev_all_cb (GObject      *object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  GOutputStream *ostream = G_OUTPUT_STREAM (object);
+  WritevAsyncData *data = user_data;
+
+  g_output_stream_writev_all_finish (ostream, result, &data->bytes_written, &data->error);
+  data->done = TRUE;
+}
+
+/* Test that writev_async_all() on local file output streams works on a non-empty vector */
+static void
+test_writev_async_all (void)
+{
+  WritevAsyncData data = { 0 };
+  GFile *file;
+  GFileIOStream *iostream = NULL;
+  GOutputStream *ostream;
+  GOutputVector vectors[3];
+  const guint8 buffer[] = {1, 2, 3, 4, 5,
+                           1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+                           1, 2, 3};
+  GError *error = NULL;
+  gboolean res;
+  guint8 *contents;
+  gsize length;
+
+  vectors[0].buffer = buffer;
+  vectors[0].size = 5;
+
+  vectors[1].buffer = buffer + 5;
+  vectors[1].size = 12;
+
+  vectors[2].buffer = buffer + 5  + 12;
+  vectors[2].size = 3;
+
+  file = g_file_new_tmp ("g_file_writev_XXXXXX",
+                         &iostream, NULL);
+  g_assert_nonnull (file);
+  g_assert_nonnull (iostream);
+
+  ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+  g_output_stream_writev_all_async (ostream, vectors, G_N_ELEMENTS (vectors), 0, NULL, test_writev_all_cb, 
&data);
+
+  while (!data.done)
+    g_main_context_iteration (NULL, TRUE);
+
+  g_assert_cmpuint (data.bytes_written, ==, sizeof buffer);
+  g_assert_no_error (data.error);
+
+  res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_object_unref (iostream);
+
+  res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+
+  g_assert_cmpmem (contents, length, buffer, sizeof buffer);
+
+  g_free (contents);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
+/* Test that writev_async_all() on local file output streams handles cancellation correctly */
+static void
+test_writev_async_all_cancellation (void)
+{
+  WritevAsyncData data = { 0 };
+  GFile *file;
+  GFileIOStream *iostream = NULL;
+  GOutputVector vectors[3];
+  const guint8 buffer[] = {1, 2, 3, 4, 5,
+                           1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+                           1, 2, 3};
+  GOutputStream *ostream;
+  GError *error = NULL;
+  gboolean res;
+  guint8 *contents;
+  gsize length;
+  GCancellable *cancellable;
+
+  vectors[0].buffer = buffer;
+  vectors[0].size = 5;
+
+  vectors[1].buffer = buffer + 5;
+  vectors[1].size = 12;
+
+  vectors[2].buffer = buffer + 5  + 12;
+  vectors[2].size = 3;
+
+  file = g_file_new_tmp ("g_file_writev_XXXXXX",
+                         &iostream, NULL);
+  g_assert_nonnull (file);
+  g_assert_nonnull (iostream);
+
+  ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+  cancellable = g_cancellable_new ();
+
+  g_output_stream_writev_all_async (ostream, vectors, G_N_ELEMENTS (vectors), 0, cancellable, 
test_writev_all_cb, &data);
+
+  g_cancellable_cancel (cancellable);
+
+  while (!data.done)
+    g_main_context_iteration (NULL, TRUE);
+
+  g_assert_cmpuint (data.bytes_written, ==, 0);
+  g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+  g_clear_error (&data.error);
+
+  res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_object_unref (iostream);
+
+  res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_assert_cmpuint (length, ==, 0);
+
+  g_free (contents);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+  g_object_unref (cancellable);
+}
+
+/* Test that writev_async_all() with empty vectors is handled correctly */
+static void
+test_writev_async_all_empty_vectors (void)
+{
+  WritevAsyncData data = { 0 };
+  GFile *file;
+  GFileIOStream *iostream = NULL;
+  GOutputVector vectors[3];
+  GOutputStream *ostream;
+  GError *error = NULL;
+  gboolean res;
+  guint8 *contents;
+  gsize length;
+
+  vectors[0].buffer = NULL;
+  vectors[0].size = 0;
+
+  vectors[1].buffer = NULL;
+  vectors[1].size = 0;
+
+  vectors[2].buffer = NULL;
+  vectors[2].size = 0;
+
+  file = g_file_new_tmp ("g_file_writev_XXXXXX",
+                         &iostream, NULL);
+  g_assert_nonnull (file);
+  g_assert_nonnull (iostream);
+
+  ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+  g_output_stream_writev_all_async (ostream, vectors, G_N_ELEMENTS (vectors), 0, NULL, test_writev_all_cb, 
&data);
+
+  while (!data.done)
+    g_main_context_iteration (NULL, TRUE);
+
+  g_assert_cmpuint (data.bytes_written, ==, 0);
+  g_assert_no_error (data.error);
+  g_clear_error (&data.error);
+
+  res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_object_unref (iostream);
+
+  res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_assert_cmpuint (length, ==, 0);
+
+  g_free (contents);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
+/* Test that writev_async_all() with no vectors is handled correctly */
+static void
+test_writev_async_all_no_vectors (void)
+{
+  WritevAsyncData data = { 0 };
+  GFile *file;
+  GFileIOStream *iostream = NULL;
+  GOutputStream *ostream;
+  GError *error = NULL;
+  gboolean res;
+  guint8 *contents;
+  gsize length;
+
+  file = g_file_new_tmp ("g_file_writev_XXXXXX",
+                         &iostream, NULL);
+  g_assert_nonnull (file);
+  g_assert_nonnull (iostream);
+
+  ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+  g_output_stream_writev_all_async (ostream, NULL, 0, 0, NULL, test_writev_all_cb, &data);
+
+  while (!data.done)
+    g_main_context_iteration (NULL, TRUE);
+
+  g_assert_cmpuint (data.bytes_written, ==, 0);
+  g_assert_no_error (data.error);
+  g_clear_error (&data.error);
+
+  res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_object_unref (iostream);
+
+  res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_assert_cmpuint (length, ==, 0);
+
+  g_free (contents);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
+/* Test that writev_async_all() with too big vectors is handled correctly */
+static void
+test_writev_async_all_too_big_vectors (void)
+{
+  WritevAsyncData data = { 0 };
+  GFile *file;
+  GFileIOStream *iostream = NULL;
+  GOutputVector vectors[3];
+  GOutputStream *ostream;
+  GError *error = NULL;
+  gboolean res;
+  guint8 *contents;
+  gsize length;
+
+  vectors[0].buffer = (void*) 1;
+  vectors[0].size = G_MAXSIZE / 2;
+
+  vectors[1].buffer = (void*) 1;
+  vectors[1].size = G_MAXSIZE / 2;
+
+  vectors[2].buffer = (void*) 1;
+  vectors[2].size = G_MAXSIZE / 2;
+
+  file = g_file_new_tmp ("g_file_writev_XXXXXX",
+                         &iostream, NULL);
+  g_assert_nonnull (file);
+  g_assert_nonnull (iostream);
+
+  ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
+  g_output_stream_writev_all_async (ostream, vectors, G_N_ELEMENTS (vectors), 0, NULL, test_writev_all_cb, 
&data);
+
+  while (!data.done)
+    g_main_context_iteration (NULL, TRUE);
+
+  g_assert_cmpuint (data.bytes_written, ==, 0);
+  g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
+  g_clear_error (&data.error);
+
+  res = g_io_stream_close (G_IO_STREAM (iostream), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_object_unref (iostream);
+
+  res = g_file_load_contents (file, NULL, (gchar **) &contents, &length, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_assert_cmpuint (length, ==, 0);
+
+  g_free (contents);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -1190,6 +1746,17 @@ main (int argc, char *argv[])
   g_test_add_func ("/file/measure-async", test_measure_async);
   g_test_add_func ("/file/load-bytes", test_load_bytes);
   g_test_add_func ("/file/load-bytes-async", test_load_bytes_async);
+  g_test_add_func ("/file/writev", test_writev);
+  g_test_add_func ("/file/writev/no-bytes-written", test_writev_no_bytes_written);
+  g_test_add_func ("/file/writev/no-vectors", test_writev_no_vectors);
+  g_test_add_func ("/file/writev/empty-vectors", test_writev_empty_vectors);
+  g_test_add_func ("/file/writev/too-big-vectors", test_writev_too_big_vectors);
+  g_test_add_func ("/file/writev/async", test_writev_async);
+  g_test_add_func ("/file/writev/async_all", test_writev_async_all);
+  g_test_add_func ("/file/writev/async_all-empty-vectors", test_writev_async_all_empty_vectors);
+  g_test_add_func ("/file/writev/async_all-no-vectors", test_writev_async_all_no_vectors);
+  g_test_add_func ("/file/writev/async_all-to-big-vectors", test_writev_async_all_too_big_vectors);
+  g_test_add_func ("/file/writev/async_all-cancellation", test_writev_async_all_cancellation);
 
   return g_test_run ();
 }
diff --git a/gio/tests/memory-output-stream.c b/gio/tests/memory-output-stream.c
index 4c85993e4..72da6263d 100644
--- a/gio/tests/memory-output-stream.c
+++ b/gio/tests/memory-output-stream.c
@@ -300,6 +300,94 @@ test_write_bytes (void)
   g_bytes_unref (bytes2);
 }
 
+/* Test that writev() works on #GMemoryOutputStream with a non-empty set of vectors. This
+ * covers the default writev() implementation around write(). */
+static void
+test_writev (void)
+{
+  GOutputStream *mo;
+  GError *error = NULL;
+  gboolean res;
+  gsize bytes_written;
+  GOutputVector vectors[3];
+  const guint8 buffer[] = {1, 2, 3, 4, 5,
+                           1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+                           1, 2, 3};
+  guint8 *output_buffer;
+
+  vectors[0].buffer = buffer;
+  vectors[0].size = 5;
+
+  vectors[1].buffer = buffer + vectors[0].size;
+  vectors[1].size = 12;
+
+  vectors[2].buffer = buffer + vectors[0].size + vectors[1].size;
+  vectors[2].size = 3;
+
+  mo = (GOutputStream*) g_object_new (G_TYPE_MEMORY_OUTPUT_STREAM,
+                                      "realloc-function", g_realloc,
+                                      "destroy-function", g_free,
+                                      NULL);
+  res = g_output_stream_writev_all (mo, vectors, G_N_ELEMENTS (vectors), &bytes_written, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_true (res);
+  g_assert_cmpuint (bytes_written, ==, sizeof buffer);
+
+  g_output_stream_close (mo, NULL, &error);
+  g_assert_no_error (error);
+
+  g_assert_cmpuint (g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mo)), ==, sizeof buffer);
+  output_buffer = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mo));
+  g_assert_cmpmem (output_buffer, sizeof buffer, buffer, sizeof buffer);
+
+  g_object_unref (mo);
+}
+
+/* Test that writev_nonblocking() works on #GMemoryOutputStream with a non-empty set of vectors. This
+ * covers the default writev_nonblocking() implementation around write_nonblocking(). */
+static void
+test_writev_nonblocking (void)
+{
+  GOutputStream *mo;
+  GError *error = NULL;
+  gboolean res;
+  gsize bytes_written;
+  GOutputVector vectors[3];
+  const guint8 buffer[] = {1, 2, 3, 4, 5,
+                           1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+                           1, 2, 3};
+  guint8 *output_buffer;
+
+  vectors[0].buffer = buffer;
+  vectors[0].size = 5;
+
+  vectors[1].buffer = buffer + vectors[0].size;
+  vectors[1].size = 12;
+
+  vectors[2].buffer = buffer + vectors[0].size + vectors[1].size;
+  vectors[2].size = 3;
+
+  mo = (GOutputStream*) g_object_new (G_TYPE_MEMORY_OUTPUT_STREAM,
+                                      "realloc-function", g_realloc,
+                                      "destroy-function", g_free,
+                                      NULL);
+  res = g_pollable_output_stream_writev_nonblocking (G_POLLABLE_OUTPUT_STREAM (mo),
+                                                     vectors, G_N_ELEMENTS (vectors),
+                                                     &bytes_written, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (res, ==, G_POLLABLE_RETURN_OK);
+  g_assert_cmpuint (bytes_written, ==, sizeof buffer);
+
+  g_output_stream_close (mo, NULL, &error);
+  g_assert_no_error (error);
+
+  g_assert_cmpuint (g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mo)), ==, sizeof buffer);
+  output_buffer = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (mo));
+  g_assert_cmpmem (output_buffer, sizeof buffer, buffer, sizeof buffer);
+
+  g_object_unref (mo);
+}
+
 static void
 test_steal_as_bytes (void)
 {
@@ -350,6 +438,8 @@ main (int   argc,
   g_test_add_func ("/memory-output-stream/get-data-size", test_data_size);
   g_test_add_func ("/memory-output-stream/properties", test_properties);
   g_test_add_func ("/memory-output-stream/write-bytes", test_write_bytes);
+  g_test_add_func ("/memory-output-stream/writev", test_writev);
+  g_test_add_func ("/memory-output-stream/writev_nonblocking", test_writev_nonblocking);
   g_test_add_func ("/memory-output-stream/steal_as_bytes", test_steal_as_bytes);
 
   return g_test_run();


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