tests: add GBytes memfd testcase
[platform/upstream/glib.git] / glib / tests / bytes.c
index 104bdce..678e881 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
+#include <unistd.h>
 #include "glib.h"
+#include "glib-unix.h"
+
+#include "glib-linux.h"
 
 static const gchar *NYAN = "nyannyan";
 static const gsize N_NYAN = 8;
@@ -25,13 +30,15 @@ test_new (void)
 {
   const gchar *data;
   GBytes *bytes;
+  gsize size;
 
   data = "test";
   bytes = g_bytes_new (data, 4);
   g_assert (bytes != NULL);
-  g_assert (g_bytes_get_data (bytes) != data);
+  g_assert (g_bytes_get_data (bytes, &size) != data);
+  g_assert_cmpuint (size, ==, 4);
   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
-  g_assert (memcmp (data, g_bytes_get_data (bytes), g_bytes_get_size (bytes)) == 0);
+  g_assert (memcmp (data, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes)) == 0);
 
   g_bytes_unref (bytes);
 }
@@ -41,11 +48,13 @@ test_new_take (void)
 {
   gchar *data;
   GBytes *bytes;
+  gsize size;
 
   data = g_strdup ("test");
   bytes = g_bytes_new_take (data, 4);
   g_assert (bytes != NULL);
-  g_assert (g_bytes_get_data (bytes) == data);
+  g_assert (g_bytes_get_data (bytes, &size) == data);
+  g_assert_cmpuint (size, ==, 4);
   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
 
   g_bytes_unref (bytes);
@@ -56,11 +65,13 @@ test_new_static (void)
 {
   const gchar *data;
   GBytes *bytes;
+  gsize size;
 
   data = "test";
   bytes = g_bytes_new_static (data, 4);
   g_assert (bytes != NULL);
-  g_assert (g_bytes_get_data (bytes) == data);
+  g_assert (g_bytes_get_data (bytes, &size) == data);
+  g_assert_cmpuint (size, ==, 4);
   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
 
   g_bytes_unref (bytes);
@@ -77,11 +88,11 @@ test_new_from_bytes (void)
   sub = g_bytes_new_from_bytes (bytes, 10, 4);
 
   g_assert (sub != NULL);
-  g_assert (g_bytes_get_data (sub) == ((gchar *)g_bytes_get_data (bytes)) + 10);
+  g_assert (g_bytes_get_data (sub, NULL) == ((gchar *)g_bytes_get_data (bytes, NULL)) + 10);
   g_assert (g_bytes_get_size (sub) == 4);
   g_bytes_unref (bytes);
 
-  g_assert (memcmp (g_bytes_get_data (sub), "wave", 4) == 0);
+  g_assert (memcmp (g_bytes_get_data (sub, NULL), "wave", 4) == 0);
   g_bytes_unref (sub);
 }
 
@@ -99,12 +110,14 @@ test_new_with_free_func (void)
   GBytes *bytes;
   gchar *data;
   gint count = 0;
+  gsize size;
 
   data = "test";
   bytes = g_bytes_new_with_free_func (data, 4, on_destroy_increment, &count);
   g_assert (bytes != NULL);
   g_assert_cmpint (count, ==, 0);
-  g_assert (g_bytes_get_data (bytes) == data);
+  g_assert (g_bytes_get_data (bytes, &size) == data);
+  g_assert_cmpuint (size, ==, 4);
   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
 
   g_bytes_unref (bytes);
@@ -200,8 +213,8 @@ test_to_data_transferred (void)
   GBytes *bytes;
 
   /* Memory transferred: one reference, and allocated with g_malloc */
-  bytes = g_bytes_new (NYAN, N_NYAN);
-  memory = g_bytes_get_data (bytes);
+  bytes = g_bytes_new_take (g_memdup (NYAN, N_NYAN), N_NYAN);
+  memory = g_bytes_get_data (bytes, NULL);
   data = g_bytes_unref_to_data (bytes, &size);
   g_assert (data == memory);
   g_assert_cmpuint (size, ==, N_NYAN);
@@ -220,13 +233,14 @@ test_to_data_two_refs (void)
   /* Memory copied: two references */
   bytes = g_bytes_new (NYAN, N_NYAN);
   bytes = g_bytes_ref (bytes);
-  memory = g_bytes_get_data (bytes);
+  memory = g_bytes_get_data (bytes, NULL);
   data = g_bytes_unref_to_data (bytes, &size);
   g_assert (data != memory);
   g_assert_cmpuint (size, ==, N_NYAN);
   g_assert (memcmp (data, NYAN, N_NYAN) == 0);
   g_free (data);
-  g_assert (g_bytes_get_data (bytes) == memory);
+  g_assert (g_bytes_get_data (bytes, &size) == memory);
+  g_assert_cmpuint (size, ==, N_NYAN);
   g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN);
   g_bytes_unref (bytes);
 }
@@ -240,7 +254,7 @@ test_to_data_non_malloc (void)
 
   /* Memory copied: non malloc memory */
   bytes = g_bytes_new_static (NYAN, N_NYAN);
-  g_assert (g_bytes_get_data (bytes) == NYAN);
+  g_assert (g_bytes_get_data (bytes, NULL) == NYAN);
   data = g_bytes_unref_to_data (bytes, &size);
   g_assert (data != (gpointer)NYAN);
   g_assert_cmpuint (size, ==, N_NYAN);
@@ -256,8 +270,8 @@ test_to_array_transferred (void)
   GBytes *bytes;
 
   /* Memory transferred: one reference, and allocated with g_malloc */
-  bytes = g_bytes_new (NYAN, N_NYAN);
-  memory = g_bytes_get_data (bytes);
+  bytes = g_bytes_new_take (g_memdup (NYAN, N_NYAN), N_NYAN);
+  memory = g_bytes_get_data (bytes, NULL);
   array = g_bytes_unref_to_array (bytes);
   g_assert (array != NULL);
   g_assert (array->data == memory);
@@ -272,18 +286,20 @@ test_to_array_two_refs (void)
   gconstpointer memory;
   GByteArray *array;
   GBytes *bytes;
+  gsize size;
 
   /* Memory copied: two references */
   bytes = g_bytes_new (NYAN, N_NYAN);
   bytes = g_bytes_ref (bytes);
-  memory = g_bytes_get_data (bytes);
+  memory = g_bytes_get_data (bytes, NULL);
   array = g_bytes_unref_to_array (bytes);
   g_assert (array != NULL);
   g_assert (array->data != memory);
   g_assert_cmpuint (array->len, ==, N_NYAN);
   g_assert (memcmp (array->data, NYAN, N_NYAN) == 0);
   g_byte_array_unref (array);
-  g_assert (g_bytes_get_data (bytes) == memory);
+  g_assert (g_bytes_get_data (bytes, &size) == memory);
+  g_assert_cmpuint (size, ==, N_NYAN);
   g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN);
   g_bytes_unref (bytes);
 }
@@ -296,7 +312,7 @@ test_to_array_non_malloc (void)
 
   /* Memory copied: non malloc memory */
   bytes = g_bytes_new_static (NYAN, N_NYAN);
-  g_assert (g_bytes_get_data (bytes) == NYAN);
+  g_assert (g_bytes_get_data (bytes, NULL) == NYAN);
   array = g_bytes_unref_to_array (bytes);
   g_assert (array != NULL);
   g_assert (array->data != (gpointer)NYAN);
@@ -305,6 +321,61 @@ test_to_array_non_malloc (void)
   g_byte_array_unref (array);
 }
 
+static void
+test_null (void)
+{
+  GBytes *bytes;
+  gpointer data;
+  gsize size;
+
+  bytes = g_bytes_new (NULL, 0);
+
+  data = g_bytes_unref_to_data (bytes, &size);
+
+  g_assert (data == NULL);
+  g_assert (size == 0);
+}
+
+#ifdef GLIB_LINUX
+static void
+test_memfd (void)
+{
+  GBytes *bytes;
+  gint fd;
+
+  fd = glib_linux_memfd_create ("", MFD_CLOEXEC);
+  if (fd == -1 && errno == EINVAL)
+    {
+      g_test_skip ("missing kernel memfd support");
+      return;
+    }
+
+  /* We should not be able to seal this one */
+  g_assert (!g_unix_fd_ensure_zero_copy_safe (fd));
+  close (fd);
+
+  /* but this one will work */
+  fd = glib_linux_memfd_create ("", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+  bytes = g_bytes_new_take_zero_copy_fd (fd);
+  g_assert_cmpint (g_bytes_get_size (bytes), ==, 0);
+  g_bytes_unref (bytes);
+
+  /* try with real data */
+  fd = glib_linux_memfd_create ("", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+  g_assert_se (write (fd, NYAN, N_NYAN) == N_NYAN);
+  bytes = g_bytes_new_take_zero_copy_fd (fd);
+  g_assert_cmpint (g_bytes_get_size (bytes), ==, N_NYAN);
+  g_assert (memcmp (g_bytes_get_data (bytes, NULL), NYAN, N_NYAN) == 0);
+  g_assert (g_bytes_get_zero_copy_fd (bytes) == fd);
+
+  /* ensure that we cannot modify the fd further */
+  g_assert_se (write (fd, NYAN, N_NYAN) == -1);
+
+  /* that's enough for now */
+  g_bytes_unref (bytes);
+}
+#endif
+
 int
 main (int argc, char *argv[])
 {
@@ -326,6 +397,10 @@ main (int argc, char *argv[])
   g_test_add_func ("/bytes/to-array/transfered", test_to_array_transferred);
   g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs);
   g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc);
+  g_test_add_func ("/bytes/null", test_null);
+#ifdef GLIB_LINUX
+  g_test_add_func ("/bytes/memfd", test_memfd);
+#endif
 
   return g_test_run ();
 }