tests: Add test for >4GB reads with g_file_load_contents()

The tests - one for sync, one for async - create a sparse file for
this purpose, so this should be cheap on the fileystem.

Of course, the test still allocates >4GB of memory for the data that it
returns from g_file_load_contents(), I hope the CI test runners can deal
with that.
This commit is contained in:
Benjamin Otte 2023-04-14 18:53:44 +02:00 committed by Philip Withnall
parent 77c35415a3
commit e74294473e

View File

@ -2928,6 +2928,144 @@ test_load_bytes_async (void)
g_main_loop_unref (data.main_loop);
}
static const gsize testfile_4gb_size = ((gsize) 1 << 32) + (1 << 16); /* 4GB + a bit */
/* @filename will be modified as per g_mkstemp() */
static gboolean
create_testfile_4gb_or_skip (char *filename)
{
GError *error = NULL;
int fd;
int ret;
fd = g_mkstemp (filename);
g_assert_cmpint (fd, !=, -1);
ret = ftruncate (fd, testfile_4gb_size);
g_clear_fd (&fd, &error);
g_assert_no_error (error);
if (ret == 1)
{
g_test_skip ("Could not create testfile >4GB");
g_assert_no_errno (g_unlink (filename));
return FALSE;
}
return TRUE;
}
static void
check_testfile_4gb_contents (const char *data,
gsize len)
{
gsize i;
g_assert_nonnull (data);
g_assert_cmpuint (testfile_4gb_size, ==, len);
for (i = 0; i < testfile_4gb_size; i++)
{
if (data[i] != 0)
break;
}
g_assert_cmpint (i, ==, testfile_4gb_size);
}
static void
test_load_contents_4gb (void)
{
char filename[] = "g_file_load_contents_4gb_XXXXXX";
GError *error = NULL;
gboolean result;
char *data;
gsize len;
GFile *file;
if (!create_testfile_4gb_or_skip (filename))
return;
file = g_file_new_for_path (filename);
result = g_file_load_contents (file, NULL, &data, &len, NULL, &error);
g_assert_no_error (error);
g_assert_true (result);
check_testfile_4gb_contents (data, len);
g_file_delete (file, NULL, NULL);
g_free (data);
g_object_unref (file);
}
static void
load_contents_4gb_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GAsyncResult **result_out = user_data;
g_assert (*result_out == NULL);
*result_out = g_object_ref (result);
g_main_context_wakeup (NULL);
}
static void
test_load_contents_4gb_async (void)
{
char filename[] = "g_file_load_contents_4gb_async_XXXXXX";
GFile *file;
GAsyncResult *async_result = NULL;
GError *error = NULL;
char *data;
gsize len;
gboolean ret;
if (!create_testfile_4gb_or_skip (filename))
return;
file = g_file_new_for_path (filename);
g_file_load_contents_async (file, NULL, load_contents_4gb_cb, &async_result);
while (async_result == NULL)
g_main_context_iteration (NULL, TRUE);
ret = g_file_load_contents_finish (file, async_result, &data, &len, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
check_testfile_4gb_contents (data, len);
g_file_delete (file, NULL, NULL);
g_free (data);
g_object_unref (async_result);
g_object_unref (file);
}
static void
test_load_bytes_4gb (void)
{
char filename[] = "g_file_load_bytes_4gb_XXXXXX";
GError *error = NULL;
GBytes *bytes;
GFile *file;
if (!create_testfile_4gb_or_skip (filename))
return;
file = g_file_new_for_path (filename);
bytes = g_file_load_bytes (file, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (bytes);
check_testfile_4gb_contents (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes));
g_file_delete (file, NULL, NULL);
g_bytes_unref (bytes);
g_object_unref (file);
}
static void
test_writev_helper (GOutputVector *vectors,
gsize n_vectors,
@ -4230,6 +4368,9 @@ 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/load-bytes-4gb", test_load_bytes_4gb);
g_test_add_func ("/file/load-contents-4gb", test_load_contents_4gb);
g_test_add_func ("/file/load-contents-4gb-async", test_load_contents_4gb_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);