diff options
author | Mayank Sharma <mayank8019@gmail.com> | 2019-08-28 08:57:32 +0530 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2020-01-31 06:54:02 +0000 |
commit | caf866440e0fb2a7a0e4b105c8a5b8c1e7875654 (patch) | |
tree | 320de6853c0e27bd865c9341c5a468b5c764dfc5 /test | |
parent | eb21143f49ca5ebea73b78bb61b4ac1fda402a97 (diff) | |
download | gvfs-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.c | 1486 | ||||
-rw-r--r-- | test/meson.build | 4 |
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, ) |