From 3821ba06b1dd320e199bd02a351b78bf0b8e15d5 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Mon, 12 Nov 2018 12:47:34 +0000 Subject: [PATCH 1/5] tests/g-file-info-filesystem-readonly: assert subcommands succeed In practice, fusermount -u often fails: /usr/bin/fusermount: failed to unmount /home/wjt/src/gnome/glib/_build/dir_bindfs_mountpoint: Device or resource busy which causes the subsequent calls to bindfs to fail: fuse: mountpoint is not empty fuse: if you are sure this is safe, use the 'nonempty' mount option This may or may not cause the current test run to fail, but it reliably causes a repeat run of the test to fail. This change causes the current run to fail instead. --- gio/tests/g-file-info-filesystem-readonly.c | 71 ++++++++++++++++----- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/gio/tests/g-file-info-filesystem-readonly.c b/gio/tests/g-file-info-filesystem-readonly.c index 123dcd8a0..ff16fbbe0 100644 --- a/gio/tests/g-file-info-filesystem-readonly.c +++ b/gio/tests/g-file-info-filesystem-readonly.c @@ -19,11 +19,48 @@ * if advised of the possibility of such damage. */ +#include #include #include #include #include +static void +run (GError **error, + const gchar *argv0, + ...) +{ + GPtrArray *args; + const gchar *arg; + va_list ap; + GSubprocess *subprocess; + + args = g_ptr_array_new (); + + va_start (ap, argv0); + g_ptr_array_add (args, (gchar *) argv0); + while ((arg = va_arg (ap, const gchar *))) + g_ptr_array_add (args, (gchar *) arg); + g_ptr_array_add (args, NULL); + va_end (ap); + + subprocess = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error); + g_ptr_array_free (args, TRUE); + + if (subprocess == NULL) + return; + + g_subprocess_wait_check (subprocess, NULL, error); + g_object_unref (subprocess); +} + +static void +assert_remove (const gchar *file) +{ + if (g_remove (file) != 0) + g_error ("failed to remove %s: %s", file, g_strerror (errno)); +} + static void test_filesystem_readonly (gconstpointer with_mount_monitor) { @@ -31,9 +68,9 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) GFile *mounted_file; GUnixMountMonitor *mount_monitor = NULL; gchar *bindfs, *fusermount; - gchar *command_mount, *command_mount_ro, *command_umount; gchar *curdir, *dir_to_mount, *dir_mountpoint; gchar *file_in_mount, *file_in_mountpoint; + GError *error = NULL; /* installed by package 'bindfs' in Fedora */ bindfs = g_find_program_in_path ("bindfs"); @@ -68,8 +105,8 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) /* Use bindfs, which does not need root privileges, to mount the contents of one dir * into another dir (and do the mount as readonly as per passed '-o ro' option) */ - command_mount_ro = g_strdup_printf ("%s -n -o ro '%s' '%s'", bindfs, dir_to_mount, dir_mountpoint); - g_spawn_command_line_sync (command_mount_ro, NULL, NULL, NULL, NULL); + run (&error, bindfs, "-n", "-o", "ro", dir_to_mount, dir_mountpoint, NULL); + g_assert_no_error (error); /* Let's check now, that the file is in indeed in a readonly filesystem */ file_in_mountpoint = g_strdup_printf ("%s/example.txt", dir_mountpoint); @@ -83,7 +120,9 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) } file_info = g_file_query_filesystem_info (mounted_file, - G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, NULL, NULL); + G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (file_info); if (! g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY)) { g_test_skip ("Failed to create readonly file needed to proceed further with the test"); @@ -91,10 +130,10 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) } /* Now we unmount, and mount again but this time rw (not readonly) */ - command_umount = g_strdup_printf ("%s -u '%s'", fusermount, dir_mountpoint); - g_spawn_command_line_sync (command_umount, NULL, NULL, NULL, NULL); - command_mount = g_strdup_printf ("%s -n '%s' '%s'", bindfs, dir_to_mount, dir_mountpoint); - g_spawn_command_line_sync (command_mount, NULL, NULL, NULL, NULL); + run (&error, fusermount, "-u", dir_mountpoint, NULL); + g_assert_no_error (error); + run (&error, bindfs, "-n", dir_to_mount, dir_mountpoint, NULL); + g_assert_no_error (error); if (with_mount_monitor) { @@ -108,7 +147,9 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) g_clear_object (&mounted_file); mounted_file = g_file_new_for_path (file_in_mountpoint); file_info = g_file_query_filesystem_info (mounted_file, - G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, NULL, NULL); + G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (file_info); if (g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY)) { @@ -128,20 +169,18 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) g_clear_object (&mount_monitor); g_clear_object (&file_info); g_clear_object (&mounted_file); - g_spawn_command_line_sync (command_umount, NULL, NULL, NULL, NULL); /* unmount */ + run (&error, fusermount, "-u", dir_mountpoint, NULL); + g_assert_no_error (error); - g_remove (file_in_mount); - g_remove (dir_to_mount); - g_remove (dir_mountpoint); + assert_remove (file_in_mount); + assert_remove (dir_to_mount); + assert_remove (dir_mountpoint); g_free (bindfs); g_free (fusermount); g_free (curdir); g_free (dir_to_mount); g_free (dir_mountpoint); - g_free (command_mount); - g_free (command_mount_ro); - g_free (command_umount); g_free (file_in_mount); g_free (file_in_mountpoint); } From 5b106cdc56f4acda353d2cd025224dc52c9ba443 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Mon, 12 Nov 2018 14:46:34 +0000 Subject: [PATCH 2/5] tests/g-file-info-filesystem-readonly: unmount lazily fusermount -z behaves like umount --lazy, which is documented thus: > Detach the filesystem from the file hierarchy now, and clean up all > references to this filesystem as soon as it is not busy anymore. Without this, the call to `fusermount -u` often fails with: /usr/bin/fusermount: failed to unmount /home/wjt/src/gnome/glib/_build/dir_bindfs_mountpoint: Device or resource busy which causes the subsequent call to bindfs to fail: fuse: mountpoint is not empty fuse: if you are sure this is safe, use the 'nonempty' mount option It's not clear what is causing the mount to be busy. Inserting a g_usleep (100 * 1000) before the calls to `fusermount -u` also works to make the problem go away, but for the purposes of this test the important point is that the mount is detached from the directory, for which a lazy unmount is fine. Fixes #1590. --- gio/tests/g-file-info-filesystem-readonly.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gio/tests/g-file-info-filesystem-readonly.c b/gio/tests/g-file-info-filesystem-readonly.c index ff16fbbe0..a1a2ca546 100644 --- a/gio/tests/g-file-info-filesystem-readonly.c +++ b/gio/tests/g-file-info-filesystem-readonly.c @@ -130,7 +130,7 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) } /* Now we unmount, and mount again but this time rw (not readonly) */ - run (&error, fusermount, "-u", dir_mountpoint, NULL); + run (&error, fusermount, "-z", "-u", dir_mountpoint, NULL); g_assert_no_error (error); run (&error, bindfs, "-n", dir_to_mount, dir_mountpoint, NULL); g_assert_no_error (error); @@ -169,7 +169,7 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) g_clear_object (&mount_monitor); g_clear_object (&file_info); g_clear_object (&mounted_file); - run (&error, fusermount, "-u", dir_mountpoint, NULL); + run (&error, fusermount, "-z", "-u", dir_mountpoint, NULL); g_assert_no_error (error); assert_remove (file_in_mount); From a2f32f6a11816cebccb6d9b1a361597dce0d6026 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Mon, 12 Nov 2018 14:52:54 +0000 Subject: [PATCH 3/5] tests/g-file-info-filesystem-readonly: remove output stream stuff This test is intended to verify the fix for https://bugzilla.gnome.org/show_bug.cgi?id=787731, which was that g_file_query_filesystem_info() would return stale information for the mount. After replacing a read-only mount with a read-write mount, this test used to only fail if G_FILE_ATTRIBUTE_FILESYSTEM_READONLY was TRUE and yet the file could be opened for writing. In particular, if (due to a test bug) the file really was still on a read-only filesystem, the test would pass. Now that we have fixed that bug in the test, we can make a stronger assertion. --- gio/tests/g-file-info-filesystem-readonly.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/gio/tests/g-file-info-filesystem-readonly.c b/gio/tests/g-file-info-filesystem-readonly.c index a1a2ca546..a715ef8d0 100644 --- a/gio/tests/g-file-info-filesystem-readonly.c +++ b/gio/tests/g-file-info-filesystem-readonly.c @@ -151,19 +151,7 @@ test_filesystem_readonly (gconstpointer with_mount_monitor) g_assert_no_error (error); g_assert_nonnull (file_info); - if (g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY)) - { - /* ¡¡ GIO still reports filesystem as being Readonly !! - * Let's check if that's true by trying to write to file */ - GFileOutputStream *write_stream; - write_stream = g_file_append_to (mounted_file, G_FILE_CREATE_NONE, NULL, NULL); - if (write_stream != NULL) - { - /* The file has been opened for writing without error, so ¡¡ GIO IS WRONG !! */ - g_object_unref (write_stream); - g_test_fail (); /* Marking test as FAILED */ - } - } + g_assert_false (g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY)); /* Clean up */ g_clear_object (&mount_monitor); From ab892acf11de79245783750785a165945d300b44 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Mon, 12 Nov 2018 12:44:19 +0000 Subject: [PATCH 4/5] ci: add bindfs and fuse to Fedora CI image Without `bindfs` and `fusermount`, all tests in g-file-info-filesystem-readonly.c are skipped. --- .gitlab-ci.yml | 2 +- .gitlab-ci/Dockerfile | 2 ++ .gitlab-ci/run-docker.sh | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7923fb506..6dee29ea4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: registry.gitlab.gnome.org/gnome/glib/master:v9 +image: registry.gitlab.gnome.org/gnome/glib/master:v10 stages: - build diff --git a/.gitlab-ci/Dockerfile b/.gitlab-ci/Dockerfile index 1a0dd11aa..aa37c7c66 100644 --- a/.gitlab-ci/Dockerfile +++ b/.gitlab-ci/Dockerfile @@ -3,9 +3,11 @@ FROM fedora:27 RUN dnf -y install \ autoconf \ automake \ + bindfs \ desktop-file-utils \ elfutils-libelf-devel \ findutils \ + fuse \ gamin-devel \ gcc \ gcc-c++ \ diff --git a/.gitlab-ci/run-docker.sh b/.gitlab-ci/run-docker.sh index 42d953857..f9a8c7513 100755 --- a/.gitlab-ci/run-docker.sh +++ b/.gitlab-ci/run-docker.sh @@ -2,7 +2,7 @@ set -e -TAG="registry.gitlab.gnome.org/gnome/glib/master:v9" +TAG="registry.gitlab.gnome.org/gnome/glib/master:v10" docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \ --file "Dockerfile" . From 1520afb451550b05a1fe0a102fd5d99817069ccc Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Tue, 13 Nov 2018 10:32:35 +0000 Subject: [PATCH 5/5] ci: document how to update the Docker image By making run-docker.sh to `cd` to the correct directory, we don't need to document that step. --- .gitlab-ci/README.md | 23 +++++++++++++++++++++++ .gitlab-ci/run-docker.sh | 1 + 2 files changed, 24 insertions(+) create mode 100644 .gitlab-ci/README.md diff --git a/.gitlab-ci/README.md b/.gitlab-ci/README.md new file mode 100644 index 000000000..41dfd7559 --- /dev/null +++ b/.gitlab-ci/README.md @@ -0,0 +1,23 @@ +# CI support stuff + +## Docker image + +GitLab CI jobs run in a Docker image, defined here. To update that image +(perhaps to install some more packages): + +1. Edit `.gitlab-ci/Dockerfile` with the changes you want +2. Edit `.gitlab-ci/run-docker.sh` and bump the version in `TAG` +3. Run `.gitlab-ci/run-docker.sh` to build the new image, and launch a shell + inside it + * When you're done, exit the shell in the usual way +4. Run `.gitlab-ci/run-docker.sh --push` to upload the new image to the GNOME + GitLab Docker registry + * If this is the first time you're doing this, you'll need to log into the + registry + * If you use 2-factor authentication on your GNOME GitLab account, you'll + need to [create a personal access token][pat] and use that rather than + your normal password +5. Edit `.gitlab-ci.yml` (in the root of this repository) to use your new + image + +[pat]: https://gitlab.gnome.org/profile/personal_access_tokens diff --git a/.gitlab-ci/run-docker.sh b/.gitlab-ci/run-docker.sh index f9a8c7513..a0caec54a 100755 --- a/.gitlab-ci/run-docker.sh +++ b/.gitlab-ci/run-docker.sh @@ -4,6 +4,7 @@ set -e TAG="registry.gitlab.gnome.org/gnome/glib/master:v10" +cd "$(dirname "$0")" docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \ --file "Dockerfile" .