summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMayank Sharma <mayank8019@gmail.com>2019-08-28 08:57:32 +0530
committerOndrej Holy <oholy@redhat.com>2020-01-31 06:54:02 +0000
commitcaf866440e0fb2a7a0e4b105c8a5b8c1e7875654 (patch)
tree320de6853c0e27bd865c9341c5a468b5c764dfc5 /test
parenteb21143f49ca5ebea73b78bb61b4ac1fda402a97 (diff)
downloadgvfs-caf866440e0fb2a7a0e4b105c8a5b8c1e7875654.tar.gz
google: Added tests for the Google Backend and updated tests/meson.build
A new set of tests have been added to test the newly implemented functionality in the Google Backend. The tests use the first GMount (linked to a valid Google account) to obtain an email address and create a libgdata service for contacting the Drive API. These tests use the GIO API directly to perform various operations automatically.
Diffstat (limited to 'test')
-rw-r--r--test/google.c1486
-rw-r--r--test/meson.build4
2 files changed, 1490 insertions, 0 deletions
diff --git a/test/google.c b/test/google.c
new file mode 100644
index 00000000..c920caba
--- /dev/null
+++ b/test/google.c
@@ -0,0 +1,1486 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2019 Mayank Sharma
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Mayank Sharma <mayank8019@gmail.com>
+ */
+
+#include <gio/gio.h>
+#include <glib.h>
+#include <locale.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <gdata/gdata.h>
+#include <goa/goa.h>
+
+#define GOOGLE_TEST_DIRECTORY "test-google"
+
+#define OP_COPY_TEST_DIRECTORY "Test-Copy-Dir"
+#define OP_MOVE_TEST_DIRECTORY "Test-Move-Dir"
+
+#define TITLE_DUMMY_FILE "Dummy-File"
+#define TITLE_COPIED_FILE "Copied-File"
+#define TITLE_MOVED_FILE "Moved-File"
+
+typedef struct {
+ GDataDocumentsService *service;
+ GDataDocumentsEntry *test_dir_entry;
+ GDataAuthorizationDomain *domain;
+ GMount *mount;
+ GFile *root; /* GFile corresponding to root-level directory */
+ GFile *test_dir; /* GFile corresponding to test_dir_entry */
+ GFile *test_dummy_file; /* A GFile inside of test_dir which can be used for
+ testing copy/move operations*/
+} GVfsGoogleTestData ;
+
+typedef struct
+{
+ GAsyncResult *res;
+ GMainLoop *loop;
+
+} MountData;
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* Helper functions begin */
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gchar *
+get_file_attribute (GFile *file, const char *attribute, GError **error)
+{
+ g_autoptr(GFileInfo) info = NULL;
+ g_autoptr(GError) child_error = NULL;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (error != NULL && *error == NULL, NULL);
+
+ info = g_file_query_info (file,
+ attribute,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return FALSE;
+ }
+
+ return g_file_info_get_attribute_as_string (info, attribute);
+}
+
+static gboolean
+delete_file_recursively (GFile *file)
+{
+ gboolean success;
+ g_autoptr (GError) error = NULL;
+
+ do
+ {
+ g_autoptr (GFileEnumerator) enumerator = NULL;
+
+ success = g_file_delete (file, NULL, &error);
+ if (success ||
+ !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY))
+ break;
+
+ g_clear_error (&error);
+ enumerator = g_file_enumerate_children (file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, &error);
+
+ if (enumerator)
+ {
+ GFileInfo *info;
+
+ success = TRUE;
+ info = g_file_enumerator_next_file (enumerator,
+ NULL,
+ &error);
+
+ while (info != NULL)
+ {
+ g_autoptr (GFile) child = NULL;
+
+ child = g_file_enumerator_get_child (enumerator, info);
+ success = success && delete_file_recursively (child);
+ g_object_unref (info);
+
+ info = g_file_enumerator_next_file (enumerator, NULL, &error);
+ }
+ }
+
+ if (error != NULL)
+ success = FALSE;
+ }
+ while (success);
+
+ return success;
+}
+
+static gboolean
+delete_and_make_new_directory (GFile *folder, GError **error)
+{
+ gboolean retval = TRUE;
+ g_autoptr(GError) child_error = NULL;
+
+ while (g_file_make_directory (folder, NULL, &child_error) == FALSE)
+ {
+ gboolean needs_delete = FALSE;
+
+ if (child_error != NULL)
+ {
+ if (child_error->code != G_IO_ERROR_EXISTS)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return FALSE;
+ }
+ else
+ needs_delete = TRUE;
+ }
+
+ child_error = NULL;
+ if (needs_delete)
+ {
+ g_file_delete (folder, NULL, &child_error);
+ if (child_error != NULL)
+ {
+ if (child_error->code != G_IO_ERROR_NOT_EMPTY)
+ {
+ retval = FALSE;
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ break;
+ }
+
+ retval = delete_file_recursively (folder);
+ }
+ }
+ }
+
+ return retval;
+}
+
+static void
+volume_mount_cb (GVolume *volume,
+ GAsyncResult *res,
+ MountData *user_data)
+{
+ MountData *data = user_data;
+ data->res = g_object_ref (res);
+ g_main_loop_quit (data->loop);
+}
+
+static gboolean
+volume_mount_sync (GVolume *volume, GMountMountFlags flags, GCancellable *cancellable, GError **error)
+{
+ g_autoptr (GMainContext) context = NULL;
+ g_autoptr (GMainLoop) loop = NULL;
+ g_autoptr(GError) child_error = NULL;
+ MountData data;
+ gboolean retval = FALSE;
+
+ context = g_main_context_new ();
+ loop = g_main_loop_new (context, FALSE);
+ g_main_context_push_thread_default (context);
+ data.loop = loop;
+
+ g_volume_mount (volume,
+ flags,
+ NULL,
+ cancellable,
+ (GAsyncReadyCallback) volume_mount_cb,
+ (gpointer) &data);
+
+ g_main_loop_run (loop);
+
+ retval = g_volume_mount_finish (volume, data.res, &child_error);
+
+ if (child_error != NULL)
+ g_propagate_error (error, g_steal_pointer (&child_error));
+
+ g_object_unref (data.res);
+ g_main_context_pop_thread_default (context);
+ return retval;
+}
+
+static GFile *
+create_temporary_duplicate_file (GFile *source_file, GError **error)
+{
+ static int file_num_counter = 0;
+ g_autofree gchar *dest_file_title = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autoptr(GError) child_error = NULL;
+ GFile *dest_file = NULL;
+ g_autoptr(GFile) dummy_dest_file = NULL;
+ g_autoptr(GFile) parent = NULL;
+ gchar rand_int_string[G_ASCII_DTOSTR_BUF_SIZE];
+
+ /* Generate a string (here created using the stringified file_num_counter) and use
+ * this string as the title of the destination file. */
+ g_ascii_dtostr (rand_int_string, G_ASCII_DTOSTR_BUF_SIZE, ++file_num_counter);
+
+ source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return NULL;
+ }
+
+ dest_file_title = g_strconcat (source_file_title, " (", rand_int_string, ")", NULL);
+
+ parent = g_file_get_parent (source_file);
+ parent_path = g_file_get_path (parent);
+ dummy_dest_file = g_file_new_build_filename (parent_path, dest_file_title, NULL);
+
+ g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return NULL;
+ }
+
+ dest_file = g_file_get_child_for_display_name (parent, dest_file_title, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return NULL;
+ }
+
+ return dest_file;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* Test init and cleanup functions begin */
+/* ---------------------------------------------------------------------------------------------------- */
+
+static inline void
+setup_google_mount_and_libgdata_service (GVfsGoogleTestData *self, GError **error)
+{
+ GList *l;
+ GoaObject *test_account_goa_object = NULL;
+ g_autofree gchar *mount_email = NULL;
+ g_autofree gchar *volume_uuid = NULL;
+ g_autolist(GoaObject) accounts = NULL;
+ g_autolist(GMount) mounts = NULL;
+ g_autoptr(GDataGoaAuthorizer) authorizer = NULL;
+ g_autoptr(GError) child_error = NULL;
+ g_autoptr(GVolumeMonitor) volume_monitor = NULL;
+ g_autoptr(GVolume) volume = NULL;
+ g_autoptr(GoaClient) client = NULL;
+
+ /* We firstly check if there exists any mount with mount_name ending in
+ * "@gmail.com" */
+ volume_monitor = g_volume_monitor_get ();
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ g_autofree gchar *mount_name = NULL;
+ mount_name = g_mount_get_name (G_MOUNT (l->data));
+ if (g_str_has_suffix (mount_name, "@gmail.com"))
+ {
+ mount_email = g_strdup (mount_name);
+ self->mount = g_object_ref (G_MOUNT (l->data));
+ }
+ }
+
+ /* Basic setup pertaining to GOA, and creation of GDataDocumentsService */
+ client = goa_client_new_sync (NULL, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ accounts = goa_client_get_accounts (client);
+ for (l = accounts; l != NULL; l = l->next)
+ {
+ const gchar *goa_account_email;
+ GoaObject *object;
+ GoaAccount *account;
+
+ object = GOA_OBJECT (l->data);
+ account = goa_object_peek_account (object);
+
+ if (g_strcmp0 (goa_account_get_provider_type (account), "google") == 0)
+ {
+ if (mount_email != NULL)
+ {
+ goa_account_email = goa_account_get_identity (account);
+ if (g_strcmp0 (goa_account_email, mount_email) == 0)
+ {
+ test_account_goa_object = GOA_OBJECT (l->data);
+ break;
+ }
+ }
+ else
+ {
+ test_account_goa_object = GOA_OBJECT (l->data);
+ mount_email = goa_account_dup_identity (account);
+ break;
+ }
+ }
+ }
+
+ if (test_account_goa_object == NULL)
+ {
+ g_error ("No GOA account found with the same email as %s", mount_email);
+ return;
+ }
+
+ /* We've found an email linked to some Google Account, but the GMount hasn't
+ * been mounted yet. So, we manually mount a GMount corresponding to this
+ * mount_email. */
+ if (self->mount == NULL)
+ {
+ g_autoptr(GFile) volume_activation_root = NULL;
+ volume_uuid = g_strconcat ("google-drive://", mount_email, "/", NULL);
+ if ((volume = g_volume_monitor_get_volume_for_uuid (volume_monitor, volume_uuid)) == NULL)
+ {
+ g_error ("No GVolume found corresponding to the UUID: %s", volume_uuid);
+ return;
+ }
+
+ volume_mount_sync (volume, G_MOUNT_MOUNT_NONE, NULL, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ volume_activation_root = g_volume_get_activation_root (volume);
+ self->mount = g_file_find_enclosing_mount (volume_activation_root, NULL, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+ }
+
+ authorizer = gdata_goa_authorizer_new (test_account_goa_object);
+ self->service = gdata_documents_service_new (GDATA_AUTHORIZER (authorizer));
+ if (self->service == NULL)
+ {
+ g_error ("Couldn't initialize libgdata service for email: %s", mount_email);
+ return;
+ }
+
+ self->domain = gdata_documents_service_get_primary_authorization_domain ();
+}
+
+static void
+gvfs_google_test_init (GVfsGoogleTestData **_self, GError **error)
+{
+ gboolean op_done;
+ g_autofree gchar *root_path = NULL;
+ g_autofree gchar *test_dir_path = NULL;
+ g_autofree gchar *test_dir_id = NULL;
+ g_autofree gchar *test_dummy_file_id = NULL;
+ g_autoptr(GError) child_error = NULL;
+ g_autoptr(GFile) root = NULL;
+ g_autoptr(GFile) test_dir = NULL;
+ g_autoptr(GFile) test_dummy_file = NULL;
+ g_autoptr(GFile) copy_test_dir = NULL;
+ g_autoptr(GFile) move_test_dir = NULL;
+ g_autoptr(GFileOutputStream) file_write_stream = NULL;
+ g_autoptr(GDataDocumentsEntry) root_entry = NULL;
+ GVfsGoogleTestData *self;
+
+ *_self = g_new0 (GVfsGoogleTestData, 1);
+ self = *_self;
+ self->mount = NULL;
+
+ setup_google_mount_and_libgdata_service (self, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ root_entry = GDATA_DOCUMENTS_ENTRY (gdata_service_query_single_entry (GDATA_SERVICE (self->service),
+ self->domain,
+ "root",
+ NULL,
+ GDATA_TYPE_DOCUMENTS_FOLDER,
+ NULL,
+ &child_error));
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ /* The GFile corresponding to the root_entry we fetched above */
+ root = g_mount_get_root (self->mount);
+ root_path = g_file_get_path (root);
+ test_dir = g_file_new_build_filename (root_path, GOOGLE_TEST_DIRECTORY, NULL);
+
+ /* We create a test directory in the root folder (on Google Drive) where all
+ * the other test files/folders shall be created */
+ g_file_make_directory (test_dir, NULL, &child_error);
+ if (child_error != NULL)
+ {
+ if (child_error->code != G_IO_ERROR_EXISTS)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+ else
+ child_error = NULL;
+ }
+
+ g_object_unref (test_dir);
+ test_dir = g_file_get_child_for_display_name (root, GOOGLE_TEST_DIRECTORY, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ self->test_dir = g_object_ref (test_dir);
+
+ test_dir_id = get_file_attribute (self->test_dir, G_FILE_ATTRIBUTE_ID_FILE, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ self->test_dir_entry = GDATA_DOCUMENTS_ENTRY (gdata_service_query_single_entry (GDATA_SERVICE (self->service),
+ self->domain,
+ test_dir_id,
+ NULL,
+ GDATA_TYPE_DOCUMENTS_FOLDER,
+ NULL,
+ &child_error));
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ g_test_message ("Test folder GFile ID: %s", test_dir_id);
+ g_test_message ("Test folder Entry ID: %s", gdata_entry_get_id (GDATA_ENTRY (self->test_dir_entry)));
+
+ /* Now we create try to create a dummy file which we'll use for testing
+ * copy/move/delete operations.If the file already exists, an error with
+ * error code G_IO_ERROR_EXISTS is returned, and we simply use that existing
+ * file for testing purposes. */
+ test_dir_path = g_file_get_path (self->test_dir);
+ test_dummy_file = g_file_new_build_filename (test_dir_path, TITLE_DUMMY_FILE, NULL);
+
+ file_write_stream = g_file_create (test_dummy_file, G_FILE_CREATE_NONE, NULL, &child_error);
+ if (child_error != NULL)
+ {
+ if (child_error->code != G_IO_ERROR_EXISTS)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+ else
+ {
+ /* We simply ignore this because if file already exists, we don't
+ * have any issues for initiating the test. */
+ child_error = NULL;
+ }
+ }
+ else
+ {
+ g_output_stream_write (G_OUTPUT_STREAM (file_write_stream), "SomeRandomText", 14, NULL, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ g_output_stream_close (G_OUTPUT_STREAM (file_write_stream), NULL, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+ }
+
+ g_object_unref (test_dummy_file);
+ test_dummy_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ test_dummy_file_id = get_file_attribute (test_dummy_file, G_FILE_ATTRIBUTE_ID_FILE, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+
+ g_test_message ("Test dummy GFile ID: %s", test_dummy_file_id);
+ self->test_dummy_file = g_object_ref (test_dummy_file);
+
+ copy_test_dir = g_file_new_build_filename (test_dir_path, OP_COPY_TEST_DIRECTORY, NULL);
+ op_done = delete_and_make_new_directory (copy_test_dir, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+ g_assert_true (op_done);
+
+ move_test_dir = g_file_new_build_filename (test_dir_path, OP_MOVE_TEST_DIRECTORY, NULL);
+ op_done = delete_and_make_new_directory (move_test_dir, &child_error);
+ if (child_error != NULL)
+ {
+ g_propagate_error (error, g_steal_pointer (&child_error));
+ return;
+ }
+ g_assert_true (op_done);
+}
+
+static void
+gvfs_google_test_exit_cleanup (GVfsGoogleTestData **_self, GError **error)
+{
+ GVfsGoogleTestData *self = *_self;
+
+ g_return_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self->test_dir_entry));
+ g_return_if_fail (GDATA_IS_DOCUMENTS_SERVICE (self->service));
+
+ g_assert_true (delete_file_recursively (self->test_dir));
+
+ g_object_unref (self->service);
+ g_object_unref (self->test_dir_entry);
+ g_object_unref (self->test_dir);
+ g_object_unref (self->test_dummy_file);
+ g_object_unref (self->mount);
+ g_free (self);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* Actual test functions begin */
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Make Directory Test Case Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+static void
+gvfs_google_test_make_directory_using_valid_display_name (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) dummy_new_folder = NULL;
+ g_autofree gchar *parent_path = NULL;
+ const gchar *folder_display_name = "Valid-Display-Name-Dir";
+
+ parent_path = g_file_get_path (self->test_dir);
+ dummy_new_folder = g_file_new_build_filename (parent_path, folder_display_name, NULL);
+
+ g_assert_true (delete_and_make_new_directory (dummy_new_folder, &error));
+ g_assert_no_error (error);
+ g_assert_true (g_file_query_exists (dummy_new_folder, NULL));
+}
+
+static void
+gvfs_google_test_make_directory_using_valid_id (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) dummy_new_folder = NULL;
+ g_autoptr(GFile) actual_new_folder1 = NULL;
+ g_autoptr(GFile) actual_new_folder2 = NULL;
+ g_autoptr(GFileInfo) info1 = NULL;
+ g_autoptr(GFileInfo) info2 = NULL;
+ g_autofree gchar *parent_path = NULL;
+ const gchar *intended_folder_title = gdata_entry_get_id (GDATA_ENTRY (self->test_dir_entry));
+ const gchar *actual_folder_title = gdata_entry_get_title (GDATA_ENTRY (self->test_dir_entry));
+
+ parent_path = g_file_get_path (self->test_dir);
+ dummy_new_folder = g_file_new_build_filename (parent_path, intended_folder_title, NULL);
+
+ g_assert_true (delete_and_make_new_directory (dummy_new_folder, &error));
+ g_assert_no_error (error);
+
+ error = NULL;
+ actual_new_folder1 = g_file_get_child_for_display_name (self->test_dir, intended_folder_title, &error);
+ g_assert_nonnull (actual_new_folder1);
+ g_assert_no_error (error);
+
+ error = NULL;
+ actual_new_folder2 = g_file_get_child_for_display_name (self->test_dir, actual_folder_title, &error);
+ g_assert_nonnull (actual_new_folder2);
+ g_assert_no_error (error);
+
+ info1 = g_file_query_info (actual_new_folder1, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (info1);
+
+ info2 = g_file_query_info (actual_new_folder2, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (info1);
+
+ g_assert_cmpstr (g_file_info_get_display_name (info1), ==, g_file_info_get_display_name (info2));
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Copy Test Case Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static void
+gvfs_google_test_copy_file_from_one_parent_to_other_using_same_title (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *dest_path = NULL;
+ g_autofree gchar *copy_test_dir_id = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) copy_test_dir = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ parent_path = g_file_get_path (self->test_dir);
+ copy_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_COPY_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (copy_test_dir);
+
+ copy_test_dir_id = get_file_attribute (copy_test_dir, G_FILE_ATTRIBUTE_ID_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (copy_test_dir_id);
+
+ dest_path = g_file_get_path (copy_test_dir);
+ dest_file = g_file_new_build_filename (dest_path, TITLE_COPIED_FILE, NULL);
+
+ op_done = g_file_copy (self->test_dummy_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_cmpstr (dest_file_actual_display_name, ==, TITLE_COPIED_FILE);
+}
+
+static void
+gvfs_google_test_copy_file_from_one_parent_to_other_using_id (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *dest_path = NULL;
+ g_autofree gchar *source_file_id = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autofree gchar *copy_test_dir_id = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) copy_test_dir = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ parent_path = g_file_get_path (self->test_dir);
+ copy_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_COPY_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (copy_test_dir);
+
+ copy_test_dir_id = get_file_attribute (copy_test_dir, G_FILE_ATTRIBUTE_ID_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (copy_test_dir_id);
+
+ source_file_id = get_file_attribute (self->test_dummy_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (copy_test_dir_id);
+
+ source_file_title = get_file_attribute (self->test_dummy_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_title);
+
+ dest_path = g_file_get_path (copy_test_dir);
+ dest_file = g_file_new_build_filename (dest_path, source_file_id, NULL);
+
+ op_done = g_file_copy (self->test_dummy_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (dest_file_actual_display_name);
+
+ g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
+}
+
+static void
+gvfs_google_test_copy_file_within_same_parent_with_title_change (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *dest_file_id = NULL;
+ g_autofree gchar *dest_file_title = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ dest_file_title = g_strconcat (TITLE_DUMMY_FILE, " (Copy)", NULL);
+ parent_path = g_file_get_path (self->test_dir);
+ dest_file = g_file_new_build_filename (parent_path, dest_file_title, NULL);
+
+ op_done = g_file_copy (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ g_clear_object (&dest_file);
+ dest_file = g_file_get_child_for_display_name (self->test_dir, dest_file_title, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (dest_file);
+
+ dest_file_id = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (dest_file_id);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_cmpstr (dest_file_actual_display_name, ==, dest_file_title);
+}
+
+static void
+gvfs_google_test_copy_file_within_same_parent_with_same_title (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dummy_dest_file = NULL;
+
+ source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_title);
+
+ parent_path = g_file_get_path (self->test_dir);
+ dummy_dest_file = g_file_new_build_filename (parent_path, source_file_title, NULL);
+
+ op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
+ g_assert_true (!op_done);
+}
+
+static void
+gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_id (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *source_file_id = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dummy_dest_file = NULL;
+
+ source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_id = get_file_attribute (source_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_id);
+
+ parent_path = g_file_get_path (self->test_dir);
+ dummy_dest_file = g_file_new_build_filename (parent_path, source_file_id, NULL);
+
+ op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
+ g_assert_true (!op_done);
+}
+
+static void
+gvfs_google_test_copy_file_within_same_parent_with_source_id_as_destination_basename (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *source_file_id = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dummy_dest_file = NULL;
+
+ source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_id = get_file_attribute (source_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_id);
+
+ parent_path = g_file_get_path (self->test_dir);
+ dummy_dest_file = g_file_new_build_filename (parent_path, source_file_id, NULL);
+
+ op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
+ g_assert_true (!op_done);
+}
+
+static void
+gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_same_title (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dummy_dest_file = NULL;
+
+ source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_title);
+
+ parent_path = g_file_get_path (self->test_dir);
+ dummy_dest_file = g_file_new_build_filename (parent_path, source_file_title, NULL);
+
+ op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
+ g_assert_true (!op_done);
+}
+
+static void
+gvfs_google_test_copy_file_from_one_parent_to_other_with_volatile_entry_collision_only (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ gchar rand_int_string[G_ASCII_DTOSTR_BUF_SIZE];
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) copy_test_dir = NULL;
+ g_autoptr(GFile) dummy_dest_file = NULL;
+
+ copy_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_COPY_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (copy_test_dir);
+
+ source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ /* Generate any random string (here created using a random integer) and use
+ * this random string as the title of the destination file. We do this so
+ * that we can cause a collision just on the volatile entry and not on the
+ * title. */
+ g_ascii_dtostr (rand_int_string, G_ASCII_DTOSTR_BUF_SIZE, rand ());
+
+ parent_path = g_file_get_path (copy_test_dir);
+ dummy_dest_file = g_file_new_build_filename (parent_path, rand_int_string, NULL);
+
+ op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Move Test Case Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static void
+gvfs_google_test_move_file_within_same_parent_without_title_change (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *dest_file_title = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ /* We need some file which we can move. So, we use test_dummy_file to create
+ * a copy of that file and move its copy around using its ID. */
+ source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ dest_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ parent_path = g_file_get_path (self->test_dir);
+ dest_file = g_file_new_build_filename (parent_path, dest_file_title, NULL);
+
+ op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
+ g_assert_false (op_done);
+}
+
+static void
+gvfs_google_test_move_file_within_same_parent_with_title_change (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *dest_file_title = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ /* We need some file which we can move. So, we use test_dummy_file to create
+ * a copy of that file and move its copy around using its ID. */
+ source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ dest_file_title = g_strconcat (TITLE_DUMMY_FILE, "_test_move_file_within_same_parent_with_title_change", NULL);
+ parent_path = g_file_get_path (self->test_dir);
+ dest_file = g_file_new_build_filename (parent_path, dest_file_title, NULL);
+
+ op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ g_clear_object (&dest_file);
+ dest_file = g_file_get_child_for_display_name (self->test_dir, dest_file_title, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (dest_file);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_cmpstr (dest_file_actual_display_name, ==, dest_file_title);
+}
+
+static void
+gvfs_google_test_move_file_from_one_parent_to_other_without_backup (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *dest_path = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) move_test_dir = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (move_test_dir);
+
+ dest_path = g_file_get_path (move_test_dir);
+ dest_file = g_file_new_build_filename (dest_path, TITLE_MOVED_FILE, NULL);
+
+ /* We need some file which we can move. So, we use test_dummy_file to create
+ * a copy of that file and move its copy around using its ID. */
+ source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_title);
+
+ dest_path = g_file_get_path (move_test_dir);
+ dest_file = g_file_new_build_filename (dest_path, source_file_title, NULL);
+
+ op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
+}
+
+static void
+gvfs_google_test_move_file_from_one_parent_to_other_with_backup (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *dest_path = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) move_test_dir = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ parent_path = g_file_get_path (self->test_dir);
+ move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (move_test_dir);
+
+ /* We need some file which we can move. So, we use test_dummy_file to create
+ * a copy of that file and move its copy around using its ID. */
+ source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_title);
+
+ dest_path = g_file_get_path (move_test_dir);
+ dest_file = g_file_new_build_filename (dest_path, source_file_title, NULL);
+
+ op_done = g_file_move (source_file, dest_file, G_FILE_COPY_BACKUP, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
+}
+
+static void
+gvfs_google_test_move_file_from_one_parent_to_other_using_same_title (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *dest_path = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) move_test_dir = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ parent_path = g_file_get_path (self->test_dir);
+ move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (move_test_dir);
+
+ /* We need some file which we can move. So, we use test_dummy_file to create
+ * a copy of that file and move its copy around using its ID. */
+ source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_title);
+
+ dest_path = g_file_get_path (move_test_dir);
+ dest_file = g_file_new_build_filename (dest_path, source_file_title, NULL);
+
+ op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
+}
+
+static void
+gvfs_google_test_move_file_from_one_parent_to_other_using_new_title (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *dest_path = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autofree gchar *new_file_title = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) move_test_dir = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ parent_path = g_file_get_path (self->test_dir);
+ move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (move_test_dir);
+
+ /* We need some file which we can move. So, we use test_dummy_file to create
+ * a copy of that file and move its copy around using its ID. */
+ source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_title);
+
+ new_file_title = g_strconcat (source_file_title, " (NewTitle)", NULL);
+ dest_path = g_file_get_path (move_test_dir);
+ dest_file = g_file_new_build_filename (dest_path, new_file_title, NULL);
+
+ op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_cmpstr (dest_file_actual_display_name, ==, new_file_title);
+}
+
+static void
+gvfs_google_test_move_file_from_one_parent_to_other_using_id (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *test_dir_path = NULL;
+ g_autofree gchar *dest_path = NULL;
+ g_autofree gchar *source_file_id = NULL;
+ g_autofree gchar *source_file_title = NULL;
+ g_autofree gchar *dest_file_actual_display_name = NULL;
+ g_autoptr(GFile) move_test_dir = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ /* We need some file which we can move. So, we use test_dummy_file to create
+ * a copy of that file and move its copy around using its ID. */
+ source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ test_dir_path = g_file_get_path (self->test_dir);
+ move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (move_test_dir);
+
+ source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_title);
+
+ source_file_id = get_file_attribute (source_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_id);
+
+ dest_path = g_file_get_path (move_test_dir);
+ dest_file = g_file_new_build_filename (dest_path, source_file_id, NULL);
+
+ op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (dest_file_actual_display_name);
+
+ g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
+}
+
+#ifdef HAVE_GDATA_DOCUMENTS_QUERY_SET_ORDER_BY
+static void
+gvfs_google_test_move_file_from_one_parent_to_other_with_both_title_and_volatile_entry_collision (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *test_dir_path = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *source_file_id = NULL;
+ g_autoptr(GFile) move_test_dir = NULL;
+ g_autoptr(GFile) source_file = NULL;
+ g_autoptr(GFile) dest_file = NULL;
+
+ /* We need some file which we can firstly copy. So, we use test_dummy_file to create
+ * a copy of that file and move its copy around using its ID. */
+ source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file);
+
+ source_file_id = get_file_attribute (source_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (source_file_id);
+
+ test_dir_path = g_file_get_path (self->test_dir);
+ move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (move_test_dir);
+
+ parent_path = g_file_get_path (move_test_dir);
+ dest_file = g_file_new_build_filename (parent_path, source_file_id, NULL);
+
+ /* The copy operation, i.e. `gio copy id1 ./id2/` (which is equivalent to
+ * `gio copy id1 ./id2/id1`) */
+ op_done = g_file_copy (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ /* The move operation, i.e. `gio move id1 ./id2/` (which is equivalent to
+ * `gio move id1 ./id2/id1`) */
+ op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+
+ /* TODO: Assert here that both the files are present */
+}
+#endif
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Delete Test Case Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static void
+gvfs_google_test_recursive_delete_test_dir_folder (gconstpointer user_data)
+{
+ GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
+ gboolean op_done;
+ g_autoptr(GError) error = NULL;
+
+ op_done = delete_and_make_new_directory (self->test_dir, &error);
+ g_assert_no_error (error);
+ g_assert_true (op_done);
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Main Function ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+gint
+main (gint argc, gchar *argv [])
+{
+ gint retval = EXIT_SUCCESS;
+ GVfsGoogleTestData *self;
+ g_autoptr(GError) error = NULL;
+
+ setlocale (LC_ALL, "");
+
+ g_test_init (&argc, &argv, NULL);
+
+ gvfs_google_test_init (&self, &error);
+ if (error != NULL)
+ {
+ g_warning ("Error (init): %s", error->message);
+ return 1;
+ }
+
+ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Make Dir test cases ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+ /* Test Scenario: We try to create a folder with its title set to the string
+ * "valid_display_name_directory".
+ *
+ * Expected Behaviour: The newly created folder has the title
+ * "valid_display_name_directory".
+ *
+ * Actual Behaviour is same as expected behaviour. */
+ g_test_add_data_func ("/make_directory/using_valid_display_name",
+ (gconstpointer) self,
+ gvfs_google_test_make_directory_using_valid_display_name);
+
+ /* Test Scenario: We try to create a folder having the title of the folder set
+ * to some other file/folder's ID. So, we try to create a new folder with
+ * self->test_dir_entry's ID.
+ *
+ * Expected Behaviour: The newly created folder has the same title as
+ * self->test_dir_entry's ID.
+ *
+ * Actual Behaviour: The newly created folder gets its title set to
+ * self->test_dir_entry's title and *NOT* its ID. The reason is well documented
+ * in the make_directory function in gvfsbackendgoogle.c */
+ g_test_add_data_func ("/make_directory/using_valid_id_of_other_directory",
+ (gconstpointer) self,
+ gvfs_google_test_make_directory_using_valid_id);
+
+ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Copy test cases ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+ /* The below test case is equivalent to the following commandline operations:
+ * (Assume that file with ID `id1` has the title $T)
+ *
+ * `gio copy id1 ./"$T (copy)"` (where id2 is the ID of a folder)
+ *
+ * This operation mimics what nautilus does when we do a Ctrl+C & Ctrl+V
+ * operation on a file inside same parent directory. It simply appends a
+ * " (copy)" to the name of the file. */
+ g_test_add_data_func ("/copy_file/within_same_parent_with_title_change",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_within_same_parent_with_title_change);
+
+ /* We try to copy a file within the same parent without changing the title, i.e. this
+ * operation corresponds to `gio copy -i ./file1_title ./file1_title` but without overwrite.
+ *
+ * This operation should supposedly fail with error code `G_IO_ERROR_EXISTS`
+ * and string "Target file already exists". */
+ g_test_add_data_func ("/copy_file/within_same_parent_with_same_title",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_within_same_parent_with_same_title);
+
+ /* We try to copy a file within the same parent and keeping the title of file
+ * to be same as the ID of source file, i.e. this operation corresponds to
+ * `gio copy -i ./id1 ./id1` but without overwrite.
+ *
+ * This operation should supposedly fail with error code `G_IO_ERROR_EXISTS`
+ * and string "Target file already exists". */
+ g_test_add_data_func ("/copy_file/within_same_parent_with_source_id_as_destination_basename",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_within_same_parent_with_source_id_as_destination_basename);
+
+ /* The below test case is equivalent to the following commandline operations:
+ *
+ * `gio copy ./id1 ./$Title$` where $Title$ is the title of file with ID `id1`.
+ *
+ * This operation should supposedly fail when done over the commandline gio
+ * tool with error code `G_IO_ERROR_FAILED` and string "Operation Not Supported".
+ * TODO: Fix the below test-case to use actual overwrite. */
+ g_test_add_data_func ("/copy_file/within_same_parent_try_overwrite_with_same_title",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_same_title);
+
+ /* The below test case is equivalent to the following commandline operations:
+ *
+ * `gio copy id1 ./id1`
+ *
+ * This operation should supposedly fail when done over the commandline gio
+ * tool with error code `G_IO_ERROR_FAILED` and string "Operation Not Supported".
+ * TODO: Fix the below test-case to use actual overwrite. */
+ g_test_add_data_func ("/copy_file/within_same_parent_try_overwrite_with_id",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_id);
+
+ /* The below test case is equivalent to the following commandline operations:
+ * `gio copy id1 id2/$Title$` (where id2 is the ID of a folder, and $Title$
+ * is the title of file with ID `id1`) */
+ g_test_add_data_func ("/copy_file/from_one_parent_to_other_using_same_title",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_from_one_parent_to_other_using_same_title);
+
+ /* The below test cases causes just a collision on the volatile entry. This
+ * is because the previously executed test copies a file into the OP_COPY_TEST_DIRECTORY.
+ * So, one volatile entry was already there because of that file, and we
+ * change the title here to only cause a collision on the volatile entry (and
+ * not the title too).
+ *
+ * It basically mimics the following case:
+ * `gio copy id1 id2/some_title`
+ * `gio copy id1 id2/some_random_title` */
+ g_test_add_data_func ("/copy_file/from_one_parent_to_other_with_volatile_entry_collision_only",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_from_one_parent_to_other_with_volatile_entry_collision_only);
+
+ /* The below test case uses the same function as the test case with
+ * identifier "/copy_file/from_one_parent_to_other" because copying
+ * file from source to destination is same as producing both kinds of
+ * collisions at once.
+ *
+ * It basically mimics the following case:
+ * `gio copy id1 id2/some_title`
+ * `gio copy id1 id2/some_title`
+ *
+ * TODO: Re-enable the below test-case once you have orderBy="modifiedDate" */
+#ifdef HAVE_GDATA_DOCUMENTS_QUERY_SET_ORDER_BY
+ g_test_add_data_func ("/copy_file/from_one_parent_to_other_with_both_title_and_volatile_entry_collision",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_from_one_parent_to_other_using_same_title);
+#endif
+
+ /* The below test case is equivalent to the following commandline operations:
+ * `gio copy id1 id2/id1` (where id2 is the ID of a folder) */
+ g_test_add_data_func ("/copy_file/from_one_parent_to_other_using_id",
+ (gconstpointer) self,
+ gvfs_google_test_copy_file_from_one_parent_to_other_using_id);
+
+ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Move test cases ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+ /* The below test case is equivalent to the following commandline operations:
+ * (Assume that file with ID `id1` has the title "title1")
+ *
+ * `gio move ./title1 ./title1`
+ *
+ * This operation will fail with an error */
+ g_test_add_data_func ("/move_file/within_same_parent_without_title_change",
+ (gconstpointer) self,
+ gvfs_google_test_move_file_within_same_parent_without_title_change);
+
+ /* The below test case is equivalent to the following commandline operations:
+ * (Assume that file with ID `id1` has the title ${TITLE})
+ *
+ * `gio move ./${TITLE} ./SomeOtherTitle`
+ *
+ * This is just a normal rename operation in POSIX world, and the backend allows this. */
+ g_test_add_data_func ("/move_file/within_same_parent_with_title_change",
+ (gconstpointer) self,
+ gvfs_google_test_move_file_within_same_parent_with_title_change);
+
+ /* The below test case is equivalent to the following commandline operations:
+ * `gio move ./id1 ./id2/$Title$` (where `id2` is the ID of a folder, and
+ * $Title$ is the title of file with ID `id1`).
+ *
+ * This is simplest case for cross directory file moving. */
+ g_test_add_data_func ("/move_file/from_one_parent_to_other_without_backup",
+ (gconstpointer) self,
+ gvfs_google_test_move_file_from_one_parent_to_other_without_backup);
+
+ /* The below test case is equivalent to the following commandline operations
+ * (with the G_FILE_COPY_BACKUP flag supplied to g_file_move function):
+ * `gio move ./id1 id2/$Title$` (where `id2` is the ID of a folder, and
+ * $Title$ is the title of file with ID `id1`)
+ *
+ * Although the g_vfs_backend_google_move () will fail with G_IO_ERROR_NOT_SUPPORTED,
+ * gio will use the fallback (copy + create + read + write + delete) to
+ * support a backup operation. */
+ g_test_add_data_func ("/move_file/from_one_parent_to_other_with_backup",
+ (gconstpointer) self,
+ gvfs_google_test_move_file_from_one_parent_to_other_with_backup);
+
+ /* The below test case is equivalent to the following commandline operations:
+ * `gio move ./id1 id2/$Title$` (where `id2` is the ID of a folder, and
+ * $Title$ is the title of file with ID `id1`) */
+ g_test_add_data_func ("/move_file/from_one_parent_to_other_using_same_title",
+ (gconstpointer) self,
+ gvfs_google_test_move_file_from_one_parent_to_other_using_same_title);
+
+ /* The below test case is equivalent to the following commandline operations:
+ * `gio move ./id1 id2/SomeNewTitle` (where `id2` is the ID of a folder, and
+ * $Title$ is the title of file with ID `id1`) */
+ g_test_add_data_func ("/move_file/from_one_parent_to_other_using_new_title",
+ (gconstpointer) self,
+ gvfs_google_test_move_file_from_one_parent_to_other_using_new_title);
+
+ /* The below test case is equivalent to the following commandline operations:
+ * `gio move ./id1 id2/id1` (where `id2` is the ID of a folder) */
+ g_test_add_data_func ("/move_file/from_one_parent_to_other_using_id",
+ (gconstpointer) self,
+ gvfs_google_test_move_file_from_one_parent_to_other_using_id);
+
+ /* The below test case is equivalent to the following commandline operations:
+ *
+ * 1. `gio copy ./id1 ./id2/` ("id2" is the real ID of a folder)
+ * 2. `gio move ./id1 ./id2/`
+ *
+ * In this, the copy operation will create a volatile entry i.e. (id1, id2) -> Entry tuple.
+ * Later, during the move operation, this volatile entry will collide with
+ * the real ID "id1". We support this operation and the below test should pass.
+ * TODO: Re-enable the below test-case once you have orderBy="modifiedDate" */
+#ifdef HAVE_GDATA_DOCUMENTS_QUERY_SET_ORDER_BY
+ g_test_add_data_func ("/move_file/from_one_parent_to_other_with_both_title_and_volatile_entry_collision",
+ (gconstpointer) self,
+ gvfs_google_test_move_file_from_one_parent_to_other_with_both_title_and_volatile_entry_collision);
+#endif
+
+ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Delete test cases ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+ /* We simply delete everything in the below case. If the backend crashes at
+ * this point, there is some issue with cache. Moreover, delete is the case
+ * which can be used to ensure the sanity of the cache. If delete wrongly
+ * removes an entry (or wrongly decreases the ref_count), there's a very high
+ * chance of getting a segfault sometime later.
+ *
+ * Also, beyond the execution of below test case, the GFile corresponding to
+ * self->test_dummy_file won't be valid since that file will be deleted. As a result,
+ * any operation done using test_dummy_file will result into an error. The memory
+ * corresponding to the test_dummy_file GFile will be freed in the cleanup
+ * function. */
+ g_test_add_data_func ("/recursive_delete/test_dir_folder",
+ (gconstpointer) self,
+ gvfs_google_test_recursive_delete_test_dir_folder);
+
+ retval = g_test_run ();
+
+ gvfs_google_test_exit_cleanup (&self, &error);
+ if (error != NULL)
+ {
+ g_warning ("Error (cleanup): %s", error->message);
+ retval = EXIT_FAILURE;
+ }
+
+ return retval;
+}
diff --git a/test/meson.build b/test/meson.build
index 552a30cf..7b6a9416 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -47,17 +47,21 @@ if enable_devel_utils
'benchmark-posix-big-files',
'benchmark-posix-small-files',
'test-query-info-stream',
+ 'google'
]
deps = [
gio_dep,
glib_dep,
+ libgdata_dep,
+ goa_dep
]
foreach test: tests
executable(
test,
test + '.c',
+ c_args: ['-DG_LOG_DOMAIN="@0@"'.format(test)],
include_directories: top_inc,
dependencies: deps,
)