(root)/
glib-2.79.0/
glib/
tests/
bytes.c
       1  /*
       2   * Copyright 2011 Collabora Ltd.
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This program is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * See the included COPYING file for more information.
      12   */
      13  
      14  #undef G_DISABLE_ASSERT
      15  
      16  #include <stdio.h>
      17  #include <stdlib.h>
      18  #include <string.h>
      19  #include "glib.h"
      20  
      21  /* Keep in sync with glib/gbytes.c */
      22  struct _GBytes
      23  {
      24    gconstpointer data;
      25    gsize size;
      26    gint ref_count;
      27    GDestroyNotify free_func;
      28    gpointer user_data;
      29  };
      30  
      31  static const gchar *NYAN = "nyannyan";
      32  static const gsize N_NYAN = 8;
      33  
      34  static void
      35  test_new (void)
      36  {
      37    const gchar *data;
      38    GBytes *bytes;
      39    gsize size;
      40  
      41    data = "test";
      42    bytes = g_bytes_new (data, 4);
      43    g_assert_nonnull (bytes);
      44    g_assert_true (g_bytes_get_data (bytes, &size) != data);
      45    g_assert_cmpuint (size, ==, 4);
      46    g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
      47    g_assert_cmpmem (data, 4, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes));
      48  
      49    g_bytes_unref (bytes);
      50  }
      51  
      52  static void
      53  test_new_take (void)
      54  {
      55    gchar *data;
      56    GBytes *bytes;
      57    gsize size;
      58  
      59    data = g_strdup ("test");
      60    bytes = g_bytes_new_take (data, 4);
      61    g_assert_nonnull (bytes);
      62    g_assert_true (g_bytes_get_data (bytes, &size) == data);
      63    g_assert_cmpuint (size, ==, 4);
      64    g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
      65  
      66    g_bytes_unref (bytes);
      67  }
      68  
      69  static void
      70  test_new_static (void)
      71  {
      72    const gchar *data;
      73    GBytes *bytes;
      74    gsize size;
      75  
      76    data = "test";
      77    bytes = g_bytes_new_static (data, 4);
      78    g_assert_nonnull (bytes);
      79    g_assert_true (g_bytes_get_data (bytes, &size) == data);
      80    g_assert_cmpuint (size, ==, 4);
      81    g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
      82  
      83    g_bytes_unref (bytes);
      84  }
      85  
      86  static void
      87  test_new_from_bytes (void)
      88  {
      89    const gchar *data = "smile and wave";
      90    GBytes *bytes;
      91    GBytes *sub;
      92  
      93    bytes = g_bytes_new (data, 14);
      94    sub = g_bytes_new_from_bytes (bytes, 10, 4);
      95  
      96    g_assert_nonnull (sub);
      97    g_assert_true (g_bytes_get_data (sub, NULL) == ((gchar *)g_bytes_get_data (bytes, NULL)) + 10);
      98    g_bytes_unref (bytes);
      99  
     100    g_assert_cmpmem (g_bytes_get_data (sub, NULL), g_bytes_get_size (sub), "wave", 4);
     101    g_bytes_unref (sub);
     102  }
     103  
     104  /* Verify that creating slices of GBytes reference the top-most bytes
     105   * at the correct offset. Ensure that intermediate GBytes are not referenced.
     106   */
     107  static void
     108  test_new_from_bytes_slice (void)
     109  {
     110    GBytes *bytes = g_bytes_new_static ("Some stupid data", strlen ("Some stupid data") + 1);
     111    GBytes *bytes1 = g_bytes_new_from_bytes (bytes, 4, 13);
     112    GBytes *bytes2 = g_bytes_new_from_bytes (bytes1, 1, 12);
     113    GBytes *bytes3 = g_bytes_new_from_bytes (bytes2, 0, 6);
     114  
     115    g_assert_cmpint (bytes->ref_count, ==, 4);
     116    g_assert_cmpint (bytes1->ref_count, ==, 1);
     117    g_assert_cmpint (bytes2->ref_count, ==, 1);
     118    g_assert_cmpint (bytes3->ref_count, ==, 1);
     119  
     120    g_assert_null (bytes->user_data);
     121    g_assert_true (bytes1->user_data == bytes);
     122    g_assert_true (bytes2->user_data == bytes);
     123    g_assert_true (bytes3->user_data == bytes);
     124  
     125    g_assert_cmpint (17, ==, g_bytes_get_size (bytes));
     126    g_assert_cmpint (13, ==, g_bytes_get_size (bytes1));
     127    g_assert_cmpint (12, ==, g_bytes_get_size (bytes2));
     128    g_assert_cmpint (6, ==, g_bytes_get_size (bytes3));
     129  
     130    g_assert_cmpint (0, ==, strncmp ("Some stupid data", (gchar *)bytes->data, 17));
     131    g_assert_cmpint (0, ==, strncmp (" stupid data", (gchar *)bytes1->data, 13));
     132    g_assert_cmpint (0, ==, strncmp ("stupid data", (gchar *)bytes2->data, 12));
     133    g_assert_cmpint (0, ==, strncmp ("stupid", (gchar *)bytes3->data, 6));
     134  
     135    g_bytes_unref (bytes);
     136    g_bytes_unref (bytes1);
     137    g_bytes_unref (bytes2);
     138    g_bytes_unref (bytes3);
     139  }
     140  
     141  /* Ensure that referencing an entire GBytes just returns the same bytes
     142   * instance (with incremented reference count) instead of a new instance.
     143   */
     144  static void
     145  test_new_from_bytes_shared_ref (void)
     146  {
     147    GBytes *bytes = g_bytes_new_static ("Some data", strlen ("Some data") + 1);
     148    GBytes *other = g_bytes_new_from_bytes (bytes, 0, g_bytes_get_size (bytes));
     149  
     150    g_assert_true (bytes == other);
     151    g_assert_cmpint (bytes->ref_count, ==, 2);
     152  
     153    g_bytes_unref (bytes);
     154    g_bytes_unref (other);
     155  }
     156  
     157  static void
     158  on_destroy_increment (gpointer data)
     159  {
     160    gint *count = data;
     161    g_assert_nonnull (count);
     162    (*count)++;
     163  }
     164  
     165  static void
     166  test_new_with_free_func (void)
     167  {
     168    GBytes *bytes;
     169    gchar *data;
     170    gint count = 0;
     171    gsize size;
     172  
     173    data = "test";
     174    bytes = g_bytes_new_with_free_func (data, 4, on_destroy_increment, &count);
     175    g_assert_nonnull (bytes);
     176    g_assert_cmpint (count, ==, 0);
     177    g_assert_true (g_bytes_get_data (bytes, &size) == data);
     178    g_assert_cmpuint (size, ==, 4);
     179    g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
     180  
     181    g_bytes_unref (bytes);
     182    g_assert_cmpuint (count, ==, 1);
     183  }
     184  
     185  static void
     186  test_hash (void)
     187  {
     188    GBytes *bytes1;
     189    GBytes *bytes2;
     190    guint hash1;
     191    guint hash2;
     192  
     193    bytes1 = g_bytes_new ("blah", 4);
     194    bytes2 = g_bytes_new ("blah", 4);
     195  
     196    hash1 = g_bytes_hash (bytes1);
     197    hash2 = g_bytes_hash (bytes2);
     198    g_assert_cmpuint (hash1,  ==, hash2);
     199  
     200    g_bytes_unref (bytes1);
     201    g_bytes_unref (bytes2);
     202  }
     203  
     204  static void
     205  test_equal (void)
     206  {
     207    GBytes *bytes;
     208    GBytes *bytes2;
     209  
     210    bytes = g_bytes_new ("blah", 4);
     211  
     212    bytes2 = g_bytes_new ("blah", 4);
     213    g_assert_true (g_bytes_equal (bytes, bytes2));
     214    g_assert_true (g_bytes_equal (bytes2, bytes));
     215    g_bytes_unref (bytes2);
     216  
     217    bytes2 = g_bytes_new ("bla", 3);
     218    g_assert_false (g_bytes_equal (bytes, bytes2));
     219    g_assert_false (g_bytes_equal (bytes2, bytes));
     220    g_bytes_unref (bytes2);
     221  
     222    bytes2 = g_bytes_new ("true", 4);
     223    g_assert_false (g_bytes_equal (bytes, bytes2));
     224    g_assert_false (g_bytes_equal (bytes2, bytes));
     225    g_bytes_unref (bytes2);
     226  
     227    g_bytes_unref (bytes);
     228  }
     229  
     230  static void
     231  test_compare (void)
     232  {
     233    GBytes *bytes;
     234    GBytes *bytes2;
     235  
     236    bytes = g_bytes_new ("blah", 4);
     237  
     238    bytes2 = g_bytes_new ("blah", 4);
     239    g_assert_cmpint (g_bytes_compare (bytes, bytes2), ==, 0);
     240    g_bytes_unref (bytes2);
     241  
     242    bytes2 = g_bytes_new ("bla", 3);
     243    g_assert_cmpint (g_bytes_compare (bytes, bytes2), >, 0);
     244    g_bytes_unref (bytes2);
     245  
     246    bytes2 = g_bytes_new ("abcd", 4);
     247    g_assert_cmpint (g_bytes_compare (bytes, bytes2), >, 0);
     248    g_bytes_unref (bytes2);
     249  
     250    bytes2 = g_bytes_new ("blahblah", 8);
     251    g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
     252    g_bytes_unref (bytes2);
     253  
     254    bytes2 = g_bytes_new ("zyx", 3);
     255    g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
     256    g_bytes_unref (bytes2);
     257  
     258    bytes2 = g_bytes_new ("zyxw", 4);
     259    g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
     260    g_bytes_unref (bytes2);
     261  
     262    g_bytes_unref (bytes);
     263  }
     264  
     265  static void
     266  test_to_data_transferred (void)
     267  {
     268    gconstpointer memory;
     269    gpointer data;
     270    gsize size;
     271    GBytes *bytes;
     272  
     273    /* Memory transferred: one reference, and allocated with g_malloc */
     274    bytes = g_bytes_new (NYAN, N_NYAN);
     275    memory = g_bytes_get_data (bytes, NULL);
     276    data = g_bytes_unref_to_data (bytes, &size);
     277    g_assert_true (data == memory);
     278    g_assert_cmpmem (data, size, NYAN, N_NYAN);
     279    g_free (data);
     280  }
     281  
     282  static void
     283  test_to_data_two_refs (void)
     284  {
     285    gconstpointer memory;
     286    gpointer data;
     287    gsize size;
     288    GBytes *bytes;
     289  
     290    /* Memory copied: two references */
     291    bytes = g_bytes_new (NYAN, N_NYAN);
     292    bytes = g_bytes_ref (bytes);
     293    memory = g_bytes_get_data (bytes, NULL);
     294    data = g_bytes_unref_to_data (bytes, &size);
     295    g_assert_true (data != memory);
     296    g_assert_cmpmem (data, size, NYAN, N_NYAN);
     297    g_free (data);
     298    g_assert_true (g_bytes_get_data (bytes, &size) == memory);
     299    g_assert_cmpuint (size, ==, N_NYAN);
     300    g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN);
     301    g_bytes_unref (bytes);
     302  }
     303  
     304  static void
     305  test_to_data_non_malloc (void)
     306  {
     307    gpointer data;
     308    gsize size;
     309    GBytes *bytes;
     310  
     311    /* Memory copied: non malloc memory */
     312    bytes = g_bytes_new_static (NYAN, N_NYAN);
     313    g_assert_true (g_bytes_get_data (bytes, NULL) == NYAN);
     314    data = g_bytes_unref_to_data (bytes, &size);
     315    g_assert_true (data != (gpointer)NYAN);
     316    g_assert_cmpmem (data, size, NYAN, N_NYAN);
     317    g_free (data);
     318  }
     319  
     320  static void
     321  test_to_data_different_free_func (void)
     322  {
     323    gpointer data;
     324    gsize size;
     325    GBytes *bytes;
     326    gchar *sentinel = g_strdup ("hello");
     327  
     328    /* Memory copied: free func and user_data don’t point to the bytes data */
     329    bytes = g_bytes_new_with_free_func (NYAN, N_NYAN, g_free, sentinel);
     330    g_assert_true (g_bytes_get_data (bytes, NULL) == NYAN);
     331  
     332    data = g_bytes_unref_to_data (bytes, &size);
     333    g_assert_true (data != (gpointer)NYAN);
     334    g_assert_cmpmem (data, size, NYAN, N_NYAN);
     335    g_free (data);
     336  
     337    /* @sentinel should not be leaked; testing that requires this test to be run
     338     * under valgrind. We can’t use a custom free func to check it isn’t leaked,
     339     * as the point of this test is to hit a condition in `try_steal_and_unref()`
     340     * which is short-circuited if the free func isn’t g_free().
     341     * See discussion in https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2152 */
     342  }
     343  
     344  static void
     345  test_to_array_transferred (void)
     346  {
     347    gconstpointer memory;
     348    GByteArray *array;
     349    GBytes *bytes;
     350  
     351    /* Memory transferred: one reference, and allocated with g_malloc */
     352    bytes = g_bytes_new (NYAN, N_NYAN);
     353    memory = g_bytes_get_data (bytes, NULL);
     354    array = g_bytes_unref_to_array (bytes);
     355    g_assert_nonnull (array);
     356    g_assert_true (array->data == memory);
     357    g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN);
     358    g_byte_array_unref (array);
     359  }
     360  
     361  static void
     362  test_to_array_transferred_oversize (void)
     363  {
     364    g_test_message ("g_bytes_unref_to_array() can only take GBytes up to "
     365                    "G_MAXUINT in length; test that longer ones are rejected");
     366  
     367    if (sizeof (guint) >= sizeof (gsize))
     368      {
     369        g_test_skip ("Skipping test as guint is not smaller than gsize");
     370      }
     371    else if (g_test_undefined ())
     372      {
     373        GByteArray *array = NULL;
     374        GBytes *bytes = NULL;
     375        gpointer data = g_memdup2 (NYAN, N_NYAN);
     376        gsize len = ((gsize) G_MAXUINT) + 1;
     377  
     378        bytes = g_bytes_new_take (data, len);
     379        g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
     380                               "g_byte_array_new_take: assertion 'len <= G_MAXUINT' failed");
     381        array = g_bytes_unref_to_array (g_steal_pointer (&bytes));
     382        g_test_assert_expected_messages ();
     383        g_assert_null (array);
     384  
     385        g_free (data);
     386      }
     387    else
     388      {
     389        g_test_skip ("Skipping test as testing undefined behaviour is disabled");
     390      }
     391  }
     392  
     393  static void
     394  test_to_array_two_refs (void)
     395  {
     396    gconstpointer memory;
     397    GByteArray *array;
     398    GBytes *bytes;
     399    gsize size;
     400  
     401    /* Memory copied: two references */
     402    bytes = g_bytes_new (NYAN, N_NYAN);
     403    bytes = g_bytes_ref (bytes);
     404    memory = g_bytes_get_data (bytes, NULL);
     405    array = g_bytes_unref_to_array (bytes);
     406    g_assert_nonnull (array);
     407    g_assert_true (array->data != memory);
     408    g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN);
     409    g_byte_array_unref (array);
     410    g_assert_true (g_bytes_get_data (bytes, &size) == memory);
     411    g_assert_cmpuint (size, ==, N_NYAN);
     412    g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN);
     413    g_bytes_unref (bytes);
     414  }
     415  
     416  static void
     417  test_to_array_non_malloc (void)
     418  {
     419    GByteArray *array;
     420    GBytes *bytes;
     421  
     422    /* Memory copied: non malloc memory */
     423    bytes = g_bytes_new_static (NYAN, N_NYAN);
     424    g_assert_true (g_bytes_get_data (bytes, NULL) == NYAN);
     425    array = g_bytes_unref_to_array (bytes);
     426    g_assert_nonnull (array);
     427    g_assert_true (array->data != (gpointer)NYAN);
     428    g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN);
     429    g_byte_array_unref (array);
     430  }
     431  
     432  static void
     433  test_null (void)
     434  {
     435    GBytes *bytes;
     436    gpointer data;
     437    gsize size;
     438  
     439    bytes = g_bytes_new (NULL, 0);
     440  
     441    data = g_bytes_unref_to_data (bytes, &size);
     442  
     443    g_assert_null (data);
     444    g_assert_cmpuint (size, ==, 0);
     445  }
     446  
     447  static void
     448  test_get_region (void)
     449  {
     450    GBytes *bytes;
     451  
     452    bytes = g_bytes_new_static (NYAN, N_NYAN);
     453  
     454    /* simple valid gets at the start */
     455    g_assert_true (g_bytes_get_region (bytes, 1, 0, 1) == NYAN);
     456    g_assert_true (g_bytes_get_region (bytes, 1, 0, N_NYAN) == NYAN);
     457  
     458    /* an invalid get because the range is too wide */
     459    g_assert_true (g_bytes_get_region (bytes, 1, 0, N_NYAN + 1) == NULL);
     460  
     461    /* an valid get, but of a zero-byte range at the end */
     462    g_assert_true (g_bytes_get_region (bytes, 1, N_NYAN, 0) == NYAN + N_NYAN);
     463  
     464    /* not a valid get because it overlap ones byte */
     465    g_assert_true (g_bytes_get_region (bytes, 1, N_NYAN, 1) == NULL);
     466  
     467    /* let's try some multiplication overflow now */
     468    g_assert_true (g_bytes_get_region (bytes, 32, 0, G_MAXSIZE / 32 + 1) == NULL);
     469    g_assert_true (g_bytes_get_region (bytes, G_MAXSIZE / 32 + 1, 0, 32) == NULL);
     470  
     471    /* and some addition overflow */
     472    g_assert_true (g_bytes_get_region (bytes, 1, G_MAXSIZE, -G_MAXSIZE) == NULL);
     473    g_assert_true (g_bytes_get_region (bytes, 1, G_MAXSSIZE, ((gsize) G_MAXSSIZE) + 1) == NULL);
     474    g_assert_true (g_bytes_get_region (bytes, 1, G_MAXSIZE, 1) == NULL);
     475  
     476    g_bytes_unref (bytes);
     477  }
     478  
     479  static void
     480  test_unref_null (void)
     481  {
     482    g_test_summary ("Test that calling g_bytes_unref() on NULL is a no-op");
     483    g_bytes_unref (NULL);
     484  }
     485  
     486  int
     487  main (int argc, char *argv[])
     488  {
     489    g_test_init (&argc, &argv, NULL);
     490  
     491    g_test_add_func ("/bytes/new", test_new);
     492    g_test_add_func ("/bytes/new-take", test_new_take);
     493    g_test_add_func ("/bytes/new-static", test_new_static);
     494    g_test_add_func ("/bytes/new-with-free-func", test_new_with_free_func);
     495    g_test_add_func ("/bytes/new-from-bytes", test_new_from_bytes);
     496    g_test_add_func ("/bytes/new-from-bytes-slice", test_new_from_bytes_slice);
     497    g_test_add_func ("/bytes/new-from-bytes-shared-ref", test_new_from_bytes_shared_ref);
     498    g_test_add_func ("/bytes/hash", test_hash);
     499    g_test_add_func ("/bytes/equal", test_equal);
     500    g_test_add_func ("/bytes/compare", test_compare);
     501    g_test_add_func ("/bytes/to-data/transferred", test_to_data_transferred);
     502    g_test_add_func ("/bytes/to-data/two-refs", test_to_data_two_refs);
     503    g_test_add_func ("/bytes/to-data/non-malloc", test_to_data_non_malloc);
     504    g_test_add_func ("/bytes/to-data/different-free-func", test_to_data_different_free_func);
     505    g_test_add_func ("/bytes/to-array/transferred", test_to_array_transferred);
     506    g_test_add_func ("/bytes/to-array/transferred/oversize", test_to_array_transferred_oversize);
     507    g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs);
     508    g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc);
     509    g_test_add_func ("/bytes/null", test_null);
     510    g_test_add_func ("/bytes/get-region", test_get_region);
     511    g_test_add_func ("/bytes/unref-null", test_unref_null);
     512  
     513    return g_test_run ();
     514  }