mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-24 19:22:11 +01:00
tests: Add tests for g_file_set_contents_full()
These exercise all the code paths I can manage without adding a load of machinery to inject faults into `write()`. Signed-off-by: Philip Withnall <withnall@endlessm.com> Helps: #1302
This commit is contained in:
parent
f35f9e918a
commit
5bf3849099
@ -950,6 +950,257 @@ test_set_contents (void)
|
|||||||
g_free (name);
|
g_free (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_contents_full (void)
|
||||||
|
{
|
||||||
|
GFileSetContentsFlags flags_mask =
|
||||||
|
G_FILE_SET_CONTENTS_ONLY_EXISTING |
|
||||||
|
G_FILE_SET_CONTENTS_DURABLE |
|
||||||
|
G_FILE_SET_CONTENTS_CONSISTENT;
|
||||||
|
gint flags;
|
||||||
|
const struct
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
EXISTING_FILE_NONE,
|
||||||
|
EXISTING_FILE_REGULAR,
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
|
EXISTING_FILE_SYMLINK,
|
||||||
|
#endif
|
||||||
|
EXISTING_FILE_DIRECTORY,
|
||||||
|
}
|
||||||
|
existing_file;
|
||||||
|
int new_mode; /* only relevant if @existing_file is %EXISTING_FILE_NONE */
|
||||||
|
gboolean use_strlen;
|
||||||
|
|
||||||
|
gboolean expected_success;
|
||||||
|
GFileError expected_error;
|
||||||
|
}
|
||||||
|
tests[] =
|
||||||
|
{
|
||||||
|
{ EXISTING_FILE_NONE, 0644, FALSE, TRUE, 0 },
|
||||||
|
{ EXISTING_FILE_NONE, 0644, TRUE, TRUE, 0 },
|
||||||
|
{ EXISTING_FILE_NONE, 0600, FALSE, TRUE, 0 },
|
||||||
|
{ EXISTING_FILE_REGULAR, 0644, FALSE, TRUE, 0 },
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
|
{ EXISTING_FILE_SYMLINK, 0644, FALSE, TRUE, 0 },
|
||||||
|
#endif
|
||||||
|
{ EXISTING_FILE_DIRECTORY, 0644, FALSE, FALSE, G_FILE_ERROR_ISDIR },
|
||||||
|
};
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
g_test_summary ("Test g_file_set_contents_full() with various flags");
|
||||||
|
|
||||||
|
for (flags = 0; flags < (gint) flags_mask; flags++)
|
||||||
|
{
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (tests); i++)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar *file_name = NULL, *link_name = NULL, *dir_name = NULL;
|
||||||
|
const gchar *set_contents_name;
|
||||||
|
gchar *buf = NULL;
|
||||||
|
gsize len;
|
||||||
|
gboolean ret;
|
||||||
|
GStatBuf statbuf;
|
||||||
|
|
||||||
|
g_test_message ("Flags %d and test %" G_GSIZE_FORMAT, flags, i);
|
||||||
|
|
||||||
|
switch (tests[i].existing_file)
|
||||||
|
{
|
||||||
|
case EXISTING_FILE_REGULAR:
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
|
case EXISTING_FILE_SYMLINK:
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
gint fd;
|
||||||
|
|
||||||
|
fd = g_file_open_tmp (NULL, &file_name, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
write (fd, "a", 1);
|
||||||
|
g_assert_no_errno (g_fsync (fd));
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
|
/* Pass an existing symlink to g_file_set_contents_full() to see
|
||||||
|
* what it does. */
|
||||||
|
if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
|
||||||
|
{
|
||||||
|
link_name = g_strconcat (file_name, ".link", NULL);
|
||||||
|
g_assert_no_errno (symlink (file_name, link_name));
|
||||||
|
|
||||||
|
set_contents_name = link_name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* !G_OS_WIN32 */
|
||||||
|
{
|
||||||
|
set_contents_name = file_name;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EXISTING_FILE_DIRECTORY:
|
||||||
|
{
|
||||||
|
dir_name = g_dir_make_tmp ("glib-fileutils-set-contents-full-XXXXXX", &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
set_contents_name = dir_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EXISTING_FILE_NONE:
|
||||||
|
{
|
||||||
|
file_name = g_build_filename (g_get_tmp_dir (), "glib-file-set-contents-full-test", NULL);
|
||||||
|
g_remove (file_name);
|
||||||
|
g_assert_false (g_file_test (file_name, G_FILE_TEST_EXISTS));
|
||||||
|
|
||||||
|
set_contents_name = file_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the file contents */
|
||||||
|
ret = g_file_set_contents_full (set_contents_name, "b",
|
||||||
|
tests[i].use_strlen ? -1 : 1,
|
||||||
|
flags, tests[i].new_mode, &error);
|
||||||
|
|
||||||
|
if (!tests[i].expected_success)
|
||||||
|
{
|
||||||
|
g_assert_error (error, G_FILE_ERROR, tests[i].expected_error);
|
||||||
|
g_assert_false (ret);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_true (ret);
|
||||||
|
|
||||||
|
/* Check the contents and mode were set correctly. The mode isn’t
|
||||||
|
* changed on existing files. */
|
||||||
|
ret = g_file_get_contents (set_contents_name, &buf, &len, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_true (ret);
|
||||||
|
g_assert_cmpstr (buf, ==, "b");
|
||||||
|
g_assert_cmpuint (len, ==, 1);
|
||||||
|
g_free (buf);
|
||||||
|
|
||||||
|
g_assert_no_errno (g_lstat (set_contents_name, &statbuf));
|
||||||
|
|
||||||
|
if (tests[i].existing_file == EXISTING_FILE_NONE)
|
||||||
|
g_assert_cmpint (statbuf.st_mode & ~S_IFMT, ==, tests[i].new_mode);
|
||||||
|
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
|
if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
|
||||||
|
{
|
||||||
|
gchar *target_contents = NULL;
|
||||||
|
|
||||||
|
/* If the @set_contents_name was a symlink, it should now be a
|
||||||
|
* regular file, and the file it pointed to should not have
|
||||||
|
* changed. */
|
||||||
|
g_assert_cmpint (statbuf.st_mode & S_IFMT, ==, S_IFREG);
|
||||||
|
|
||||||
|
g_file_get_contents (file_name, &target_contents, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_cmpstr (target_contents, ==, "a");
|
||||||
|
|
||||||
|
g_free (target_contents);
|
||||||
|
}
|
||||||
|
#endif /* !G_OS_WIN32 */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir_name != NULL)
|
||||||
|
g_rmdir (dir_name);
|
||||||
|
if (link_name != NULL)
|
||||||
|
g_remove (link_name);
|
||||||
|
if (file_name != NULL)
|
||||||
|
g_remove (file_name);
|
||||||
|
|
||||||
|
g_free (dir_name);
|
||||||
|
g_free (link_name);
|
||||||
|
g_free (file_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_contents_full_read_only_file (void)
|
||||||
|
{
|
||||||
|
gint fd;
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar *file_name = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_test_summary ("Test g_file_set_contents_full() on a read-only file");
|
||||||
|
|
||||||
|
/* Can’t test this with different #GFileSetContentsFlags as they all have
|
||||||
|
* different behaviours wrt replacing the file while noticing/ignoring the
|
||||||
|
* existing file permissions. */
|
||||||
|
fd = g_file_open_tmp (NULL, &file_name, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
write (fd, "a", 1);
|
||||||
|
g_assert_no_errno (g_fsync (fd));
|
||||||
|
close (fd);
|
||||||
|
g_assert_no_errno (chmod (file_name, 0200));
|
||||||
|
|
||||||
|
/* Set the file contents */
|
||||||
|
ret = g_file_set_contents_full (file_name, "b", 1, G_FILE_SET_CONTENTS_NONE, 0644, &error);
|
||||||
|
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
|
||||||
|
g_assert_false (ret);
|
||||||
|
g_clear_error (&error);
|
||||||
|
|
||||||
|
g_remove (file_name);
|
||||||
|
|
||||||
|
g_free (file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_set_contents_full_read_only_directory (void)
|
||||||
|
{
|
||||||
|
GFileSetContentsFlags flags_mask =
|
||||||
|
G_FILE_SET_CONTENTS_ONLY_EXISTING |
|
||||||
|
G_FILE_SET_CONTENTS_DURABLE |
|
||||||
|
G_FILE_SET_CONTENTS_CONSISTENT;
|
||||||
|
gint flags;
|
||||||
|
|
||||||
|
g_test_summary ("Test g_file_set_contents_full() on a file in a read-only directory");
|
||||||
|
|
||||||
|
for (flags = 0; flags < (gint) flags_mask; flags++)
|
||||||
|
{
|
||||||
|
gint fd;
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar *dir_name = NULL;
|
||||||
|
gchar *file_name = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_test_message ("Flags %d", flags);
|
||||||
|
|
||||||
|
dir_name = g_dir_make_tmp ("glib-file-set-contents-full-rodir-XXXXXX", &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
file_name = g_build_filename (dir_name, "file", NULL);
|
||||||
|
fd = g_open (file_name, O_CREAT | O_RDWR, 0644);
|
||||||
|
g_assert_cmpint (fd, >=, 0);
|
||||||
|
write (fd, "a", 1);
|
||||||
|
g_assert_no_errno (g_fsync (fd));
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
g_assert_no_errno (chmod (dir_name, 0));
|
||||||
|
|
||||||
|
/* Set the file contents */
|
||||||
|
ret = g_file_set_contents_full (file_name, "b", 1, flags, 0644, &error);
|
||||||
|
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
|
||||||
|
g_assert_false (ret);
|
||||||
|
g_clear_error (&error);
|
||||||
|
|
||||||
|
g_remove (file_name);
|
||||||
|
g_unlink (dir_name);
|
||||||
|
|
||||||
|
g_free (file_name);
|
||||||
|
g_free (dir_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_read_link (void)
|
test_read_link (void)
|
||||||
{
|
{
|
||||||
@ -1545,6 +1796,9 @@ main (int argc,
|
|||||||
g_test_add_func ("/fileutils/mkstemp", test_mkstemp);
|
g_test_add_func ("/fileutils/mkstemp", test_mkstemp);
|
||||||
g_test_add_func ("/fileutils/mkdtemp", test_mkdtemp);
|
g_test_add_func ("/fileutils/mkdtemp", test_mkdtemp);
|
||||||
g_test_add_func ("/fileutils/set-contents", test_set_contents);
|
g_test_add_func ("/fileutils/set-contents", test_set_contents);
|
||||||
|
g_test_add_func ("/fileutils/set-contents-full", test_set_contents_full);
|
||||||
|
g_test_add_func ("/fileutils/set-contents-full/read-only-file", test_set_contents_full_read_only_file);
|
||||||
|
g_test_add_func ("/fileutils/set-contents-full/read-only-directory", test_set_contents_full_read_only_directory);
|
||||||
g_test_add_func ("/fileutils/read-link", test_read_link);
|
g_test_add_func ("/fileutils/read-link", test_read_link);
|
||||||
g_test_add_func ("/fileutils/stdio-wrappers", test_stdio_wrappers);
|
g_test_add_func ("/fileutils/stdio-wrappers", test_stdio_wrappers);
|
||||||
g_test_add_func ("/fileutils/fopen-modes", test_fopen_modes);
|
g_test_add_func ("/fileutils/fopen-modes", test_fopen_modes);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user