1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* gvfs - extensions for gio
3  *
4  * Copyright (C) 2019 Mayank Sharma
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General
17  * Public License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * Author: Mayank Sharma <mayank8019@gmail.com>
22  */
23 
24 #include <gio/gio.h>
25 #include <glib.h>
26 #include <locale.h>
27 
28 #define GOA_API_IS_SUBJECT_TO_CHANGE
29 #include <gdata/gdata.h>
30 #include <goa/goa.h>
31 
32 #define GOOGLE_TEST_DIRECTORY "test-google"
33 
34 #define OP_COPY_TEST_DIRECTORY "Test-Copy-Dir"
35 #define OP_MOVE_TEST_DIRECTORY "Test-Move-Dir"
36 
37 #define TITLE_DUMMY_FILE "Dummy-File"
38 #define TITLE_COPIED_FILE "Copied-File"
39 #define TITLE_MOVED_FILE "Moved-File"
40 
41 typedef struct {
42   GDataDocumentsService     *service;
43   GDataDocumentsEntry       *test_dir_entry;
44   GDataAuthorizationDomain  *domain;
45   GMount                    *mount;
46   GFile                     *root;                /* GFile corresponding to root-level directory */
47   GFile                     *test_dir;            /* GFile corresponding to test_dir_entry */
48   GFile                     *test_dummy_file;     /* A GFile inside of test_dir which can be used for
49                                                  testing copy/move operations*/
50 } GVfsGoogleTestData ;
51 
52 typedef struct
53 {
54   GAsyncResult *res;
55   GMainLoop *loop;
56 
57 } MountData;
58 
59 /* ---------------------------------------------------------------------------------------------------- */
60 /* Helper functions begin */
61 /* ---------------------------------------------------------------------------------------------------- */
62 
63 static gchar *
get_file_attribute(GFile * file,const char * attribute,GError ** error)64 get_file_attribute (GFile *file, const char *attribute, GError **error)
65 {
66   g_autoptr(GFileInfo) info = NULL;
67   g_autoptr(GError) child_error = NULL;
68 
69   g_return_val_if_fail (G_IS_FILE (file), NULL);
70   g_return_val_if_fail (error != NULL && *error == NULL, NULL);
71 
72   info = g_file_query_info (file,
73                             attribute,
74                             G_FILE_QUERY_INFO_NONE,
75                             NULL,
76                             &child_error);
77   if (child_error != NULL)
78     {
79       g_propagate_error (error, g_steal_pointer (&child_error));
80       return FALSE;
81     }
82 
83   return g_file_info_get_attribute_as_string (info, attribute);
84 }
85 
86 static gboolean
delete_file_recursively(GFile * file)87 delete_file_recursively (GFile *file)
88 {
89   gboolean success;
90   g_autoptr (GError) error = NULL;
91 
92   do
93     {
94       g_autoptr (GFileEnumerator) enumerator = NULL;
95 
96       success = g_file_delete (file, NULL, &error);
97       if (success ||
98           !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY))
99         break;
100 
101       g_clear_error (&error);
102       enumerator = g_file_enumerate_children (file,
103                                               G_FILE_ATTRIBUTE_STANDARD_NAME,
104                                               G_FILE_QUERY_INFO_NONE,
105                                               NULL, &error);
106 
107       if (enumerator)
108         {
109           GFileInfo *info;
110 
111           success = TRUE;
112           info = g_file_enumerator_next_file (enumerator,
113                                               NULL,
114                                               &error);
115 
116           while (info != NULL)
117             {
118               g_autoptr (GFile) child = NULL;
119 
120               child = g_file_enumerator_get_child (enumerator, info);
121               success = success && delete_file_recursively (child);
122               g_object_unref (info);
123 
124               info = g_file_enumerator_next_file (enumerator, NULL, &error);
125             }
126         }
127 
128       if (error != NULL)
129         success = FALSE;
130     }
131   while (success);
132 
133   return success;
134 }
135 
136 static gboolean
delete_and_make_new_directory(GFile * folder,GError ** error)137 delete_and_make_new_directory (GFile *folder, GError **error)
138 {
139   gboolean retval = TRUE;
140   g_autoptr(GError) child_error = NULL;
141 
142   while (g_file_make_directory (folder, NULL, &child_error) == FALSE)
143     {
144       gboolean needs_delete = FALSE;
145 
146       if (child_error != NULL)
147         {
148           if (child_error->code != G_IO_ERROR_EXISTS)
149             {
150               g_propagate_error (error, g_steal_pointer (&child_error));
151               return FALSE;
152             }
153           else
154             needs_delete = TRUE;
155         }
156 
157       child_error = NULL;
158       if (needs_delete)
159         {
160           g_file_delete (folder, NULL, &child_error);
161           if (child_error != NULL)
162             {
163               if (child_error->code != G_IO_ERROR_NOT_EMPTY)
164                 {
165                   retval = FALSE;
166                   g_propagate_error (error, g_steal_pointer (&child_error));
167                   break;
168                 }
169 
170               retval = delete_file_recursively (folder);
171             }
172         }
173     }
174 
175   return retval;
176 }
177 
178 static void
volume_mount_cb(GVolume * volume,GAsyncResult * res,MountData * user_data)179 volume_mount_cb (GVolume           *volume,
180                  GAsyncResult      *res,
181                  MountData         *user_data)
182 {
183   MountData *data = user_data;
184   data->res = g_object_ref (res);
185   g_main_loop_quit (data->loop);
186 }
187 
188 static gboolean
volume_mount_sync(GVolume * volume,GMountMountFlags flags,GCancellable * cancellable,GError ** error)189 volume_mount_sync (GVolume *volume, GMountMountFlags flags, GCancellable *cancellable, GError **error)
190 {
191   g_autoptr (GMainContext) context  = NULL;
192   g_autoptr (GMainLoop) loop = NULL;
193   g_autoptr(GError) child_error = NULL;
194   MountData data;
195   gboolean retval = FALSE;
196 
197   context = g_main_context_new ();
198   loop = g_main_loop_new (context, FALSE);
199   g_main_context_push_thread_default (context);
200   data.loop = loop;
201 
202   g_volume_mount (volume,
203                   flags,
204                   NULL,
205                   cancellable,
206                   (GAsyncReadyCallback) volume_mount_cb,
207                   (gpointer) &data);
208 
209   g_main_loop_run (loop);
210 
211   retval = g_volume_mount_finish (volume, data.res, &child_error);
212 
213   if (child_error != NULL)
214     g_propagate_error (error, g_steal_pointer (&child_error));
215 
216   g_object_unref (data.res);
217   g_main_context_pop_thread_default (context);
218   return retval;
219 }
220 
221 static GFile *
create_temporary_duplicate_file(GFile * source_file,GError ** error)222 create_temporary_duplicate_file (GFile *source_file, GError **error)
223 {
224   static int file_num_counter = 0;
225   g_autofree gchar *dest_file_title = NULL;
226   g_autofree gchar *source_file_title = NULL;
227   g_autofree gchar *parent_path = NULL;
228   g_autoptr(GError) child_error = NULL;
229   GFile *dest_file = NULL;
230   g_autoptr(GFile) dummy_dest_file = NULL;
231   g_autoptr(GFile) parent = NULL;
232   gchar rand_int_string[G_ASCII_DTOSTR_BUF_SIZE];
233 
234   /* Generate a string (here created using the stringified file_num_counter) and use
235    * this string as the title of the destination file. */
236   g_ascii_dtostr (rand_int_string, G_ASCII_DTOSTR_BUF_SIZE, ++file_num_counter);
237 
238   source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &child_error);
239   if (child_error != NULL)
240     {
241       g_propagate_error (error, g_steal_pointer (&child_error));
242       return NULL;
243     }
244 
245   dest_file_title = g_strconcat (source_file_title, " (", rand_int_string, ")", NULL);
246 
247   parent = g_file_get_parent (source_file);
248   parent_path = g_file_get_path (parent);
249   dummy_dest_file = g_file_new_build_filename (parent_path, dest_file_title, NULL);
250 
251   g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &child_error);
252   if (child_error != NULL)
253     {
254       g_propagate_error (error, g_steal_pointer (&child_error));
255       return NULL;
256     }
257 
258   dest_file = g_file_get_child_for_display_name (parent, dest_file_title, &child_error);
259   if (child_error != NULL)
260     {
261       g_propagate_error (error, g_steal_pointer (&child_error));
262       return NULL;
263     }
264 
265   return dest_file;
266 }
267 
268 /* ---------------------------------------------------------------------------------------------------- */
269 /* Test init and cleanup functions begin */
270 /* ---------------------------------------------------------------------------------------------------- */
271 
272 static inline void
setup_google_mount_and_libgdata_service(GVfsGoogleTestData * self,GError ** error)273 setup_google_mount_and_libgdata_service (GVfsGoogleTestData *self, GError **error)
274 {
275   GList *l;
276   GoaObject *test_account_goa_object = NULL;
277   g_autofree gchar *mount_email = NULL;
278   g_autofree gchar *volume_uuid = NULL;
279   g_autolist(GoaObject) accounts = NULL;
280   g_autolist(GMount) mounts = NULL;
281   g_autoptr(GDataGoaAuthorizer) authorizer = NULL;
282   g_autoptr(GError) child_error = NULL;
283   g_autoptr(GVolumeMonitor) volume_monitor = NULL;
284   g_autoptr(GVolume) volume = NULL;
285   g_autoptr(GoaClient) client = NULL;
286 
287   /* We firstly check if there exists any mount with mount_name ending in
288    * "@gmail.com" */
289   volume_monitor = g_volume_monitor_get ();
290   mounts = g_volume_monitor_get_mounts (volume_monitor);
291   for (l = mounts; l != NULL; l = l->next)
292     {
293       g_autofree gchar *mount_name = NULL;
294       mount_name = g_mount_get_name (G_MOUNT (l->data));
295       if (g_str_has_suffix (mount_name, "@gmail.com"))
296         {
297           mount_email = g_strdup (mount_name);
298           self->mount = g_object_ref (G_MOUNT (l->data));
299         }
300     }
301 
302   /* Basic setup pertaining to GOA, and creation of GDataDocumentsService */
303   client = goa_client_new_sync (NULL, &child_error);
304   if (child_error != NULL)
305     {
306       g_propagate_error (error, g_steal_pointer (&child_error));
307       return;
308     }
309 
310   accounts = goa_client_get_accounts (client);
311   for (l = accounts; l != NULL; l = l->next)
312     {
313       const gchar *goa_account_email;
314       GoaObject *object;
315       GoaAccount *account;
316 
317       object = GOA_OBJECT (l->data);
318       account = goa_object_peek_account (object);
319 
320       if (g_strcmp0 (goa_account_get_provider_type (account), "google") == 0)
321         {
322           if (mount_email != NULL)
323             {
324               goa_account_email = goa_account_get_identity (account);
325               if (g_strcmp0 (goa_account_email, mount_email) == 0)
326                 {
327                   test_account_goa_object = GOA_OBJECT (l->data);
328                   break;
329                 }
330             }
331           else
332             {
333               test_account_goa_object = GOA_OBJECT (l->data);
334               mount_email = goa_account_dup_identity (account);
335               break;
336             }
337         }
338     }
339 
340   if (test_account_goa_object == NULL)
341     {
342       g_error ("No GOA account found with the same email as %s", mount_email);
343       return;
344     }
345 
346   /* We've found an email linked to some Google Account, but the GMount hasn't
347    * been mounted yet. So, we manually mount a GMount corresponding to this
348    * mount_email. */
349   if (self->mount == NULL)
350     {
351       g_autoptr(GFile) volume_activation_root = NULL;
352       volume_uuid = g_strconcat ("google-drive://", mount_email, "/", NULL);
353       if ((volume = g_volume_monitor_get_volume_for_uuid (volume_monitor, volume_uuid)) == NULL)
354         {
355           g_error ("No GVolume found corresponding to the UUID: %s", volume_uuid);
356           return;
357         }
358 
359       volume_mount_sync (volume, G_MOUNT_MOUNT_NONE, NULL, &child_error);
360       if (child_error != NULL)
361         {
362           g_propagate_error (error, g_steal_pointer (&child_error));
363           return;
364         }
365 
366       volume_activation_root = g_volume_get_activation_root (volume);
367       self->mount = g_file_find_enclosing_mount (volume_activation_root, NULL, &child_error);
368       if (child_error != NULL)
369         {
370           g_propagate_error (error, g_steal_pointer (&child_error));
371           return;
372         }
373     }
374 
375   authorizer = gdata_goa_authorizer_new (test_account_goa_object);
376   self->service = gdata_documents_service_new (GDATA_AUTHORIZER (authorizer));
377   if (self->service == NULL)
378     {
379       g_error ("Couldn't initialize libgdata service for email: %s", mount_email);
380       return;
381     }
382 
383   self->domain = gdata_documents_service_get_primary_authorization_domain ();
384 }
385 
386 static void
gvfs_google_test_init(GVfsGoogleTestData ** _self,GError ** error)387 gvfs_google_test_init (GVfsGoogleTestData **_self, GError **error)
388 {
389   gboolean op_done;
390   g_autofree gchar *root_path = NULL;
391   g_autofree gchar *test_dir_path = NULL;
392   g_autofree gchar *test_dir_id = NULL;
393   g_autofree gchar *test_dummy_file_id = NULL;
394   g_autoptr(GError) child_error = NULL;
395   g_autoptr(GFile) root = NULL;
396   g_autoptr(GFile) test_dir = NULL;
397   g_autoptr(GFile) test_dummy_file = NULL;
398   g_autoptr(GFile) copy_test_dir = NULL;
399   g_autoptr(GFile) move_test_dir = NULL;
400   g_autoptr(GFileOutputStream) file_write_stream = NULL;
401   g_autoptr(GDataDocumentsEntry) root_entry = NULL;
402   GVfsGoogleTestData *self;
403 
404   *_self = g_new0 (GVfsGoogleTestData, 1);
405   self = *_self;
406   self->mount = NULL;
407 
408   setup_google_mount_and_libgdata_service (self, &child_error);
409   if (child_error != NULL)
410     {
411       g_propagate_error (error, g_steal_pointer (&child_error));
412       return;
413     }
414 
415   root_entry = GDATA_DOCUMENTS_ENTRY (gdata_service_query_single_entry (GDATA_SERVICE (self->service),
416                                                                         self->domain,
417                                                                         "root",
418                                                                         NULL,
419                                                                         GDATA_TYPE_DOCUMENTS_FOLDER,
420                                                                         NULL,
421                                                                         &child_error));
422   if (child_error != NULL)
423     {
424       g_propagate_error (error, g_steal_pointer (&child_error));
425       return;
426     }
427 
428   /* The GFile corresponding to the root_entry we fetched above */
429   root = g_mount_get_root (self->mount);
430   root_path = g_file_get_path (root);
431   test_dir = g_file_new_build_filename (root_path, GOOGLE_TEST_DIRECTORY, NULL);
432 
433   /* We create a test directory in the root folder (on Google Drive) where all
434    * the other test files/folders shall be created */
435   g_file_make_directory (test_dir, NULL, &child_error);
436   if (child_error != NULL)
437     {
438       if (child_error->code != G_IO_ERROR_EXISTS)
439         {
440           g_propagate_error (error, g_steal_pointer (&child_error));
441           return;
442         }
443       else
444         child_error = NULL;
445     }
446 
447   g_object_unref (test_dir);
448   test_dir = g_file_get_child_for_display_name (root, GOOGLE_TEST_DIRECTORY, &child_error);
449   if (child_error != NULL)
450     {
451       g_propagate_error (error, g_steal_pointer (&child_error));
452       return;
453     }
454 
455   self->test_dir = g_object_ref (test_dir);
456 
457   test_dir_id = get_file_attribute (self->test_dir, G_FILE_ATTRIBUTE_ID_FILE, &child_error);
458   if (child_error != NULL)
459     {
460       g_propagate_error (error, g_steal_pointer (&child_error));
461       return;
462     }
463 
464   self->test_dir_entry = GDATA_DOCUMENTS_ENTRY (gdata_service_query_single_entry (GDATA_SERVICE (self->service),
465                                                                                   self->domain,
466                                                                                   test_dir_id,
467                                                                                   NULL,
468                                                                                   GDATA_TYPE_DOCUMENTS_FOLDER,
469                                                                                   NULL,
470                                                                                   &child_error));
471   if (child_error != NULL)
472     {
473       g_propagate_error (error, g_steal_pointer (&child_error));
474       return;
475     }
476 
477   g_test_message ("Test folder GFile ID: %s", test_dir_id);
478   g_test_message ("Test folder Entry ID: %s", gdata_entry_get_id (GDATA_ENTRY (self->test_dir_entry)));
479 
480   /* Now we create try to create a dummy file which we'll use for testing
481    * copy/move/delete operations.If the file already exists, an error with
482    * error code G_IO_ERROR_EXISTS is returned, and we simply use that existing
483    * file for testing purposes. */
484   test_dir_path = g_file_get_path (self->test_dir);
485   test_dummy_file = g_file_new_build_filename (test_dir_path, TITLE_DUMMY_FILE, NULL);
486 
487   file_write_stream = g_file_create (test_dummy_file, G_FILE_CREATE_NONE, NULL, &child_error);
488   if (child_error != NULL)
489     {
490       if (child_error->code != G_IO_ERROR_EXISTS)
491         {
492           g_propagate_error (error, g_steal_pointer (&child_error));
493           return;
494         }
495       else
496         {
497           /* We simply ignore this because if file already exists, we don't
498            * have any issues for initiating the test. */
499           child_error = NULL;
500         }
501     }
502   else
503     {
504       g_output_stream_write (G_OUTPUT_STREAM (file_write_stream), "SomeRandomText", 14, NULL, &child_error);
505       if (child_error != NULL)
506         {
507           g_propagate_error (error, g_steal_pointer (&child_error));
508           return;
509         }
510 
511       g_output_stream_close (G_OUTPUT_STREAM (file_write_stream), NULL, &child_error);
512       if (child_error != NULL)
513         {
514           g_propagate_error (error, g_steal_pointer (&child_error));
515           return;
516         }
517     }
518 
519   g_object_unref (test_dummy_file);
520   test_dummy_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &child_error);
521   if (child_error != NULL)
522     {
523       g_propagate_error (error, g_steal_pointer (&child_error));
524       return;
525     }
526 
527   test_dummy_file_id = get_file_attribute (test_dummy_file, G_FILE_ATTRIBUTE_ID_FILE, &child_error);
528   if (child_error != NULL)
529     {
530       g_propagate_error (error, g_steal_pointer (&child_error));
531       return;
532     }
533 
534   g_test_message ("Test dummy GFile ID: %s", test_dummy_file_id);
535   self->test_dummy_file = g_object_ref (test_dummy_file);
536 
537   copy_test_dir = g_file_new_build_filename (test_dir_path, OP_COPY_TEST_DIRECTORY, NULL);
538   op_done = delete_and_make_new_directory (copy_test_dir, &child_error);
539   if (child_error != NULL)
540     {
541       g_propagate_error (error, g_steal_pointer (&child_error));
542       return;
543     }
544   g_assert_true (op_done);
545 
546   move_test_dir = g_file_new_build_filename (test_dir_path, OP_MOVE_TEST_DIRECTORY, NULL);
547   op_done = delete_and_make_new_directory (move_test_dir, &child_error);
548   if (child_error != NULL)
549     {
550       g_propagate_error (error, g_steal_pointer (&child_error));
551       return;
552     }
553   g_assert_true (op_done);
554 }
555 
556 static void
gvfs_google_test_exit_cleanup(GVfsGoogleTestData ** _self,GError ** error)557 gvfs_google_test_exit_cleanup (GVfsGoogleTestData **_self, GError **error)
558 {
559   GVfsGoogleTestData *self = *_self;
560 
561   g_return_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self->test_dir_entry));
562   g_return_if_fail (GDATA_IS_DOCUMENTS_SERVICE (self->service));
563 
564   g_assert_true (delete_file_recursively (self->test_dir));
565 
566   g_object_unref (self->service);
567   g_object_unref (self->test_dir_entry);
568   g_object_unref (self->test_dir);
569   g_object_unref (self->test_dummy_file);
570   g_object_unref (self->mount);
571   g_free (self);
572 }
573 
574 /* ---------------------------------------------------------------------------------------------------- */
575 /* Actual test functions begin */
576 /* ---------------------------------------------------------------------------------------------------- */
577 
578 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Make Directory Test Case Functions  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
579 static void
gvfs_google_test_make_directory_using_valid_display_name(gconstpointer user_data)580 gvfs_google_test_make_directory_using_valid_display_name (gconstpointer user_data)
581 {
582   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
583   g_autoptr(GError) error = NULL;
584   g_autoptr(GFile) dummy_new_folder = NULL;
585   g_autofree gchar *parent_path = NULL;
586   const gchar *folder_display_name = "Valid-Display-Name-Dir";
587 
588   parent_path = g_file_get_path (self->test_dir);
589   dummy_new_folder = g_file_new_build_filename (parent_path, folder_display_name, NULL);
590 
591   g_assert_true (delete_and_make_new_directory (dummy_new_folder, &error));
592   g_assert_no_error (error);
593   g_assert_true (g_file_query_exists (dummy_new_folder, NULL));
594 }
595 
596 static void
gvfs_google_test_make_directory_using_valid_id(gconstpointer user_data)597 gvfs_google_test_make_directory_using_valid_id (gconstpointer user_data)
598 {
599   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
600   g_autoptr(GError) error = NULL;
601   g_autoptr(GFile) dummy_new_folder = NULL;
602   g_autoptr(GFile) actual_new_folder1 = NULL;
603   g_autoptr(GFile) actual_new_folder2 = NULL;
604   g_autoptr(GFileInfo) info1 = NULL;
605   g_autoptr(GFileInfo) info2 = NULL;
606   g_autofree gchar *parent_path = NULL;
607   const gchar *intended_folder_title = gdata_entry_get_id (GDATA_ENTRY (self->test_dir_entry));
608   const gchar *actual_folder_title = gdata_entry_get_title (GDATA_ENTRY (self->test_dir_entry));
609 
610   parent_path = g_file_get_path (self->test_dir);
611   dummy_new_folder = g_file_new_build_filename (parent_path, intended_folder_title, NULL);
612 
613   g_assert_true (delete_and_make_new_directory (dummy_new_folder, &error));
614   g_assert_no_error (error);
615 
616   error = NULL;
617   actual_new_folder1 = g_file_get_child_for_display_name (self->test_dir, intended_folder_title, &error);
618   g_assert_nonnull (actual_new_folder1);
619   g_assert_no_error (error);
620 
621   error = NULL;
622   actual_new_folder2 = g_file_get_child_for_display_name (self->test_dir, actual_folder_title, &error);
623   g_assert_nonnull (actual_new_folder2);
624   g_assert_no_error (error);
625 
626   info1 = g_file_query_info (actual_new_folder1, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, &error);
627   g_assert_no_error (error);
628   g_assert_nonnull (info1);
629 
630   info2 = g_file_query_info (actual_new_folder2, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, &error);
631   g_assert_no_error (error);
632   g_assert_nonnull (info1);
633 
634   g_assert_cmpstr (g_file_info_get_display_name (info1), ==, g_file_info_get_display_name (info2));
635 }
636 
637 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Copy Test Case Functions  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
638 
639 static void
gvfs_google_test_copy_file_from_one_parent_to_other_using_same_title(gconstpointer user_data)640 gvfs_google_test_copy_file_from_one_parent_to_other_using_same_title (gconstpointer user_data)
641 {
642   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
643   gboolean op_done;
644   g_autoptr(GError) error = NULL;
645   g_autofree gchar *parent_path = NULL;
646   g_autofree gchar *dest_path = NULL;
647   g_autofree gchar *copy_test_dir_id = NULL;
648   g_autofree gchar *dest_file_actual_display_name = NULL;
649   g_autoptr(GFile) copy_test_dir = NULL;
650   g_autoptr(GFile) dest_file = NULL;
651 
652   parent_path = g_file_get_path (self->test_dir);
653   copy_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_COPY_TEST_DIRECTORY, &error);
654   g_assert_no_error (error);
655   g_assert_nonnull (copy_test_dir);
656 
657   copy_test_dir_id = get_file_attribute (copy_test_dir, G_FILE_ATTRIBUTE_ID_FILE, &error);
658   g_assert_no_error (error);
659   g_assert_nonnull (copy_test_dir_id);
660 
661   dest_path = g_file_get_path (copy_test_dir);
662   dest_file = g_file_new_build_filename (dest_path, TITLE_COPIED_FILE, NULL);
663 
664   op_done = g_file_copy (self->test_dummy_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
665   g_assert_no_error (error);
666   g_assert_true (op_done);
667 
668   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
669   g_assert_no_error (error);
670   g_assert_cmpstr (dest_file_actual_display_name, ==, TITLE_COPIED_FILE);
671 }
672 
673 static void
gvfs_google_test_copy_file_from_one_parent_to_other_using_id(gconstpointer user_data)674 gvfs_google_test_copy_file_from_one_parent_to_other_using_id (gconstpointer user_data)
675 {
676   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
677   gboolean op_done;
678   g_autoptr(GError) error = NULL;
679   g_autofree gchar *parent_path = NULL;
680   g_autofree gchar *dest_path = NULL;
681   g_autofree gchar *source_file_id = NULL;
682   g_autofree gchar *source_file_title = NULL;
683   g_autofree gchar *copy_test_dir_id = NULL;
684   g_autofree gchar *dest_file_actual_display_name = NULL;
685   g_autoptr(GFile) copy_test_dir = NULL;
686   g_autoptr(GFile) dest_file = NULL;
687 
688   parent_path = g_file_get_path (self->test_dir);
689   copy_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_COPY_TEST_DIRECTORY, &error);
690   g_assert_no_error (error);
691   g_assert_nonnull (copy_test_dir);
692 
693   copy_test_dir_id = get_file_attribute (copy_test_dir, G_FILE_ATTRIBUTE_ID_FILE, &error);
694   g_assert_no_error (error);
695   g_assert_nonnull (copy_test_dir_id);
696 
697   source_file_id = get_file_attribute (self->test_dummy_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
698   g_assert_no_error (error);
699   g_assert_nonnull (copy_test_dir_id);
700 
701   source_file_title = get_file_attribute (self->test_dummy_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
702   g_assert_no_error (error);
703   g_assert_nonnull (source_file_title);
704 
705   dest_path = g_file_get_path (copy_test_dir);
706   dest_file = g_file_new_build_filename (dest_path, source_file_id, NULL);
707 
708   op_done = g_file_copy (self->test_dummy_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
709   g_assert_no_error (error);
710   g_assert_true (op_done);
711 
712   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
713   g_assert_no_error (error);
714   g_assert_nonnull (dest_file_actual_display_name);
715 
716   g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
717 }
718 
719 static void
gvfs_google_test_copy_file_within_same_parent_with_title_change(gconstpointer user_data)720 gvfs_google_test_copy_file_within_same_parent_with_title_change (gconstpointer user_data)
721 {
722   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
723   gboolean op_done;
724   g_autoptr(GError) error = NULL;
725   g_autofree gchar *parent_path = NULL;
726   g_autofree gchar *dest_file_id = NULL;
727   g_autofree gchar *dest_file_title = NULL;
728   g_autofree gchar *dest_file_actual_display_name = NULL;
729   g_autoptr(GFile) source_file = NULL;
730   g_autoptr(GFile) dest_file = NULL;
731 
732   source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
733   g_assert_no_error (error);
734   g_assert_nonnull (source_file);
735 
736   dest_file_title = g_strconcat (TITLE_DUMMY_FILE, " (Copy)", NULL);
737   parent_path = g_file_get_path (self->test_dir);
738   dest_file = g_file_new_build_filename (parent_path, dest_file_title, NULL);
739 
740   op_done = g_file_copy (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
741   g_assert_no_error (error);
742   g_assert_true (op_done);
743 
744   g_clear_object (&dest_file);
745   dest_file = g_file_get_child_for_display_name (self->test_dir, dest_file_title, &error);
746   g_assert_no_error (error);
747   g_assert_nonnull (dest_file);
748 
749   dest_file_id = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
750   g_assert_no_error (error);
751   g_assert_nonnull (dest_file_id);
752 
753   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
754   g_assert_no_error (error);
755   g_assert_cmpstr (dest_file_actual_display_name, ==, dest_file_title);
756 }
757 
758 static void
gvfs_google_test_copy_file_within_same_parent_with_same_title(gconstpointer user_data)759 gvfs_google_test_copy_file_within_same_parent_with_same_title (gconstpointer user_data)
760 {
761   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
762   gboolean op_done;
763   g_autoptr(GError) error = NULL;
764   g_autofree gchar *parent_path = NULL;
765   g_autofree gchar *source_file_title = NULL;
766   g_autoptr(GFile) source_file = NULL;
767   g_autoptr(GFile) dummy_dest_file = NULL;
768 
769   source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
770   g_assert_no_error (error);
771   g_assert_nonnull (source_file);
772 
773   source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
774   g_assert_no_error (error);
775   g_assert_nonnull (source_file_title);
776 
777   parent_path = g_file_get_path (self->test_dir);
778   dummy_dest_file = g_file_new_build_filename (parent_path, source_file_title, NULL);
779 
780   op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
781   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
782   g_assert_true (!op_done);
783 }
784 
785 static void
gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_id(gconstpointer user_data)786 gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_id (gconstpointer user_data)
787 {
788   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
789   gboolean op_done;
790   g_autoptr(GError) error = NULL;
791   g_autofree gchar *parent_path = NULL;
792   g_autofree gchar *source_file_id = NULL;
793   g_autoptr(GFile) source_file = NULL;
794   g_autoptr(GFile) dummy_dest_file = NULL;
795 
796   source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
797   g_assert_no_error (error);
798   g_assert_nonnull (source_file);
799 
800   source_file_id = get_file_attribute (source_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
801   g_assert_no_error (error);
802   g_assert_nonnull (source_file_id);
803 
804   parent_path = g_file_get_path (self->test_dir);
805   dummy_dest_file = g_file_new_build_filename (parent_path, source_file_id, NULL);
806 
807   op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
808   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
809   g_assert_true (!op_done);
810 }
811 
812 static void
gvfs_google_test_copy_file_within_same_parent_with_source_id_as_destination_basename(gconstpointer user_data)813 gvfs_google_test_copy_file_within_same_parent_with_source_id_as_destination_basename (gconstpointer user_data)
814 {
815   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
816   gboolean op_done;
817   g_autoptr(GError) error = NULL;
818   g_autofree gchar *parent_path = NULL;
819   g_autofree gchar *source_file_id = NULL;
820   g_autoptr(GFile) source_file = NULL;
821   g_autoptr(GFile) dummy_dest_file = NULL;
822 
823   source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
824   g_assert_no_error (error);
825   g_assert_nonnull (source_file);
826 
827   source_file_id = get_file_attribute (source_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
828   g_assert_no_error (error);
829   g_assert_nonnull (source_file_id);
830 
831   parent_path = g_file_get_path (self->test_dir);
832   dummy_dest_file = g_file_new_build_filename (parent_path, source_file_id, NULL);
833 
834   op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
835   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
836   g_assert_true (!op_done);
837 }
838 
839 static void
gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_same_title(gconstpointer user_data)840 gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_same_title (gconstpointer user_data)
841 {
842   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
843   gboolean op_done;
844   g_autoptr(GError) error = NULL;
845   g_autofree gchar *parent_path = NULL;
846   g_autofree gchar *source_file_title = NULL;
847   g_autoptr(GFile) source_file = NULL;
848   g_autoptr(GFile) dummy_dest_file = NULL;
849 
850   source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
851   g_assert_no_error (error);
852   g_assert_nonnull (source_file);
853 
854   source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
855   g_assert_no_error (error);
856   g_assert_nonnull (source_file_title);
857 
858   parent_path = g_file_get_path (self->test_dir);
859   dummy_dest_file = g_file_new_build_filename (parent_path, source_file_title, NULL);
860 
861   op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
862   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
863   g_assert_true (!op_done);
864 }
865 
866 static void
gvfs_google_test_copy_file_from_one_parent_to_other_with_volatile_entry_collision_only(gconstpointer user_data)867 gvfs_google_test_copy_file_from_one_parent_to_other_with_volatile_entry_collision_only (gconstpointer user_data)
868 {
869   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
870   gboolean op_done;
871   gchar rand_int_string[G_ASCII_DTOSTR_BUF_SIZE];
872   g_autoptr(GError) error = NULL;
873   g_autofree gchar *parent_path = NULL;
874   g_autoptr(GFile) source_file = NULL;
875   g_autoptr(GFile) copy_test_dir = NULL;
876   g_autoptr(GFile) dummy_dest_file = NULL;
877 
878   copy_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_COPY_TEST_DIRECTORY, &error);
879   g_assert_no_error (error);
880   g_assert_nonnull (copy_test_dir);
881 
882   source_file = g_file_get_child_for_display_name (self->test_dir, TITLE_DUMMY_FILE, &error);
883   g_assert_no_error (error);
884   g_assert_nonnull (source_file);
885 
886   /* Generate any random string (here created using a random integer) and use
887    * this random string as the title of the destination file. We do this so
888    * that we can cause a collision just on the volatile entry and not on the
889    * title. */
890   g_ascii_dtostr (rand_int_string, G_ASCII_DTOSTR_BUF_SIZE, rand ());
891 
892   parent_path = g_file_get_path (copy_test_dir);
893   dummy_dest_file = g_file_new_build_filename (parent_path, rand_int_string, NULL);
894 
895   op_done = g_file_copy (source_file, dummy_dest_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
896   g_assert_no_error (error);
897   g_assert_true (op_done);
898 }
899 
900 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Move Test Case Functions  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
901 
902 static void
gvfs_google_test_move_file_within_same_parent_without_title_change(gconstpointer user_data)903 gvfs_google_test_move_file_within_same_parent_without_title_change (gconstpointer user_data)
904 {
905   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
906   gboolean op_done;
907   g_autoptr(GError) error = NULL;
908   g_autofree gchar *parent_path = NULL;
909   g_autofree gchar *dest_file_title = NULL;
910   g_autoptr(GFile) source_file = NULL;
911   g_autoptr(GFile) dest_file = NULL;
912 
913   /* We need some file which we can move. So, we use test_dummy_file to create
914    * a copy of that file and move its copy around using its ID. */
915   source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
916   g_assert_no_error (error);
917   g_assert_nonnull (source_file);
918 
919   dest_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
920   parent_path = g_file_get_path (self->test_dir);
921   dest_file = g_file_new_build_filename (parent_path, dest_file_title, NULL);
922 
923   op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
924   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
925   g_assert_false (op_done);
926 }
927 
928 static void
gvfs_google_test_move_file_within_same_parent_with_title_change(gconstpointer user_data)929 gvfs_google_test_move_file_within_same_parent_with_title_change (gconstpointer user_data)
930 {
931   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
932   gboolean op_done;
933   g_autoptr(GError) error = NULL;
934   g_autofree gchar *parent_path = NULL;
935   g_autofree gchar *dest_file_title = NULL;
936   g_autofree gchar *dest_file_actual_display_name = NULL;
937   g_autoptr(GFile) source_file = NULL;
938   g_autoptr(GFile) dest_file = NULL;
939 
940   /* We need some file which we can move. So, we use test_dummy_file to create
941    * a copy of that file and move its copy around using its ID. */
942   source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
943   g_assert_no_error (error);
944   g_assert_nonnull (source_file);
945 
946   dest_file_title = g_strconcat (TITLE_DUMMY_FILE, "_test_move_file_within_same_parent_with_title_change", NULL);
947   parent_path = g_file_get_path (self->test_dir);
948   dest_file = g_file_new_build_filename (parent_path, dest_file_title, NULL);
949 
950   op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
951   g_assert_no_error (error);
952   g_assert_true (op_done);
953 
954   g_clear_object (&dest_file);
955   dest_file = g_file_get_child_for_display_name (self->test_dir, dest_file_title, &error);
956   g_assert_no_error (error);
957   g_assert_nonnull (dest_file);
958 
959   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
960   g_assert_no_error (error);
961   g_assert_cmpstr (dest_file_actual_display_name, ==, dest_file_title);
962 }
963 
964 static void
gvfs_google_test_move_file_from_one_parent_to_other_without_backup(gconstpointer user_data)965 gvfs_google_test_move_file_from_one_parent_to_other_without_backup (gconstpointer user_data)
966 {
967   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
968   gboolean op_done;
969   g_autoptr(GError) error = NULL;
970   g_autofree gchar *dest_path = NULL;
971   g_autofree gchar *source_file_title = NULL;
972   g_autofree gchar *dest_file_actual_display_name = NULL;
973   g_autoptr(GFile) move_test_dir = NULL;
974   g_autoptr(GFile) source_file = NULL;
975   g_autoptr(GFile) dest_file = NULL;
976 
977   move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
978   g_assert_no_error (error);
979   g_assert_nonnull (move_test_dir);
980 
981   dest_path = g_file_get_path (move_test_dir);
982   dest_file = g_file_new_build_filename (dest_path, TITLE_MOVED_FILE, NULL);
983 
984   /* We need some file which we can move. So, we use test_dummy_file to create
985    * a copy of that file and move its copy around using its ID. */
986   source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
987   g_assert_no_error (error);
988   g_assert_nonnull (source_file);
989 
990   source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
991   g_assert_no_error (error);
992   g_assert_nonnull (source_file_title);
993 
994   dest_path = g_file_get_path (move_test_dir);
995   dest_file = g_file_new_build_filename (dest_path, source_file_title, NULL);
996 
997   op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
998   g_assert_no_error (error);
999   g_assert_true (op_done);
1000 
1001   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1002   g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
1003 }
1004 
1005 static void
gvfs_google_test_move_file_from_one_parent_to_other_with_backup(gconstpointer user_data)1006 gvfs_google_test_move_file_from_one_parent_to_other_with_backup (gconstpointer user_data)
1007 {
1008   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
1009   gboolean op_done;
1010   g_autoptr(GError) error = NULL;
1011   g_autofree gchar *parent_path = NULL;
1012   g_autofree gchar *dest_path = NULL;
1013   g_autofree gchar *source_file_title = NULL;
1014   g_autofree gchar *dest_file_actual_display_name = NULL;
1015   g_autoptr(GFile) move_test_dir = NULL;
1016   g_autoptr(GFile) source_file = NULL;
1017   g_autoptr(GFile) dest_file = NULL;
1018 
1019   parent_path = g_file_get_path (self->test_dir);
1020   move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
1021   g_assert_no_error (error);
1022   g_assert_nonnull (move_test_dir);
1023 
1024   /* We need some file which we can move. So, we use test_dummy_file to create
1025    * a copy of that file and move its copy around using its ID. */
1026   source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
1027   g_assert_no_error (error);
1028   g_assert_nonnull (source_file);
1029 
1030   source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1031   g_assert_no_error (error);
1032   g_assert_nonnull (source_file_title);
1033 
1034   dest_path = g_file_get_path (move_test_dir);
1035   dest_file = g_file_new_build_filename (dest_path, source_file_title, NULL);
1036 
1037   op_done = g_file_move (source_file, dest_file, G_FILE_COPY_BACKUP, NULL, NULL, NULL, &error);
1038   g_assert_no_error (error);
1039   g_assert_true (op_done);
1040 
1041   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1042   g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
1043 }
1044 
1045 static void
gvfs_google_test_move_file_from_one_parent_to_other_using_same_title(gconstpointer user_data)1046 gvfs_google_test_move_file_from_one_parent_to_other_using_same_title (gconstpointer user_data)
1047 {
1048   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
1049   gboolean op_done;
1050   g_autoptr(GError) error = NULL;
1051   g_autofree gchar *parent_path = NULL;
1052   g_autofree gchar *dest_path = NULL;
1053   g_autofree gchar *source_file_title = NULL;
1054   g_autofree gchar *dest_file_actual_display_name = NULL;
1055   g_autoptr(GFile) move_test_dir = NULL;
1056   g_autoptr(GFile) source_file = NULL;
1057   g_autoptr(GFile) dest_file = NULL;
1058 
1059   parent_path = g_file_get_path (self->test_dir);
1060   move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
1061   g_assert_no_error (error);
1062   g_assert_nonnull (move_test_dir);
1063 
1064   /* We need some file which we can move. So, we use test_dummy_file to create
1065    * a copy of that file and move its copy around using its ID. */
1066   source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
1067   g_assert_no_error (error);
1068   g_assert_nonnull (source_file);
1069 
1070   source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1071   g_assert_no_error (error);
1072   g_assert_nonnull (source_file_title);
1073 
1074   dest_path = g_file_get_path (move_test_dir);
1075   dest_file = g_file_new_build_filename (dest_path, source_file_title, NULL);
1076 
1077   op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
1078   g_assert_no_error (error);
1079   g_assert_true (op_done);
1080 
1081   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1082   g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
1083 }
1084 
1085 static void
gvfs_google_test_move_file_from_one_parent_to_other_using_new_title(gconstpointer user_data)1086 gvfs_google_test_move_file_from_one_parent_to_other_using_new_title (gconstpointer user_data)
1087 {
1088   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
1089   gboolean op_done;
1090   g_autoptr(GError) error = NULL;
1091   g_autofree gchar *parent_path = NULL;
1092   g_autofree gchar *dest_path = NULL;
1093   g_autofree gchar *source_file_title = NULL;
1094   g_autofree gchar *new_file_title = NULL;
1095   g_autofree gchar *dest_file_actual_display_name = NULL;
1096   g_autoptr(GFile) move_test_dir = NULL;
1097   g_autoptr(GFile) source_file = NULL;
1098   g_autoptr(GFile) dest_file = NULL;
1099 
1100   parent_path = g_file_get_path (self->test_dir);
1101   move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
1102   g_assert_no_error (error);
1103   g_assert_nonnull (move_test_dir);
1104 
1105   /* We need some file which we can move. So, we use test_dummy_file to create
1106    * a copy of that file and move its copy around using its ID. */
1107   source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
1108   g_assert_no_error (error);
1109   g_assert_nonnull (source_file);
1110 
1111   source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1112   g_assert_no_error (error);
1113   g_assert_nonnull (source_file_title);
1114 
1115   new_file_title = g_strconcat (source_file_title, " (NewTitle)", NULL);
1116   dest_path = g_file_get_path (move_test_dir);
1117   dest_file = g_file_new_build_filename (dest_path, new_file_title, NULL);
1118 
1119   op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
1120   g_assert_no_error (error);
1121   g_assert_true (op_done);
1122 
1123   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1124   g_assert_cmpstr (dest_file_actual_display_name, ==, new_file_title);
1125 }
1126 
1127 static void
gvfs_google_test_move_file_from_one_parent_to_other_using_id(gconstpointer user_data)1128 gvfs_google_test_move_file_from_one_parent_to_other_using_id (gconstpointer user_data)
1129 {
1130   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
1131   gboolean op_done;
1132   g_autoptr(GError) error = NULL;
1133   g_autofree gchar *test_dir_path = NULL;
1134   g_autofree gchar *dest_path = NULL;
1135   g_autofree gchar *source_file_id = NULL;
1136   g_autofree gchar *source_file_title = NULL;
1137   g_autofree gchar *dest_file_actual_display_name = NULL;
1138   g_autoptr(GFile) move_test_dir = NULL;
1139   g_autoptr(GFile) source_file = NULL;
1140   g_autoptr(GFile) dest_file = NULL;
1141 
1142   /* We need some file which we can move. So, we use test_dummy_file to create
1143    * a copy of that file and move its copy around using its ID.   */
1144   source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
1145   g_assert_no_error (error);
1146   g_assert_nonnull (source_file);
1147 
1148   test_dir_path = g_file_get_path (self->test_dir);
1149   move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
1150   g_assert_no_error (error);
1151   g_assert_nonnull (move_test_dir);
1152 
1153   source_file_title = get_file_attribute (source_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1154   g_assert_no_error (error);
1155   g_assert_nonnull (source_file_title);
1156 
1157   source_file_id = get_file_attribute (source_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
1158   g_assert_no_error (error);
1159   g_assert_nonnull (source_file_id);
1160 
1161   dest_path = g_file_get_path (move_test_dir);
1162   dest_file = g_file_new_build_filename (dest_path, source_file_id, NULL);
1163 
1164   op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
1165   g_assert_no_error (error);
1166   g_assert_true (op_done);
1167 
1168   dest_file_actual_display_name = get_file_attribute (dest_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, &error);
1169   g_assert_no_error (error);
1170   g_assert_nonnull (dest_file_actual_display_name);
1171 
1172   g_assert_cmpstr (dest_file_actual_display_name, ==, source_file_title);
1173 }
1174 
1175 #ifdef HAVE_GDATA_DOCUMENTS_QUERY_SET_ORDER_BY
1176 static void
gvfs_google_test_move_file_from_one_parent_to_other_with_both_title_and_volatile_entry_collision(gconstpointer user_data)1177 gvfs_google_test_move_file_from_one_parent_to_other_with_both_title_and_volatile_entry_collision (gconstpointer user_data)
1178 {
1179   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
1180   gboolean op_done;
1181   g_autoptr(GError) error = NULL;
1182   g_autofree gchar *test_dir_path = NULL;
1183   g_autofree gchar *parent_path = NULL;
1184   g_autofree gchar *source_file_id = NULL;
1185   g_autoptr(GFile) move_test_dir = NULL;
1186   g_autoptr(GFile) source_file = NULL;
1187   g_autoptr(GFile) dest_file = NULL;
1188 
1189   /* We need some file which we can firstly copy. So, we use test_dummy_file to create
1190    * a copy of that file and move its copy around using its ID.  */
1191   source_file = create_temporary_duplicate_file (self->test_dummy_file, &error);
1192   g_assert_no_error (error);
1193   g_assert_nonnull (source_file);
1194 
1195   source_file_id = get_file_attribute (source_file, G_FILE_ATTRIBUTE_ID_FILE, &error);
1196   g_assert_no_error (error);
1197   g_assert_nonnull (source_file_id);
1198 
1199   test_dir_path = g_file_get_path (self->test_dir);
1200   move_test_dir = g_file_get_child_for_display_name (self->test_dir, OP_MOVE_TEST_DIRECTORY, &error);
1201   g_assert_no_error (error);
1202   g_assert_nonnull (move_test_dir);
1203 
1204   parent_path = g_file_get_path (move_test_dir);
1205   dest_file = g_file_new_build_filename (parent_path, source_file_id, NULL);
1206 
1207   /* The copy operation, i.e. `gio copy id1 ./id2/` (which is equivalent to
1208    * `gio copy id1 ./id2/id1`)  */
1209   op_done = g_file_copy (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
1210   g_assert_no_error (error);
1211   g_assert_true (op_done);
1212 
1213   /* The move operation, i.e. `gio move id1 ./id2/` (which is equivalent to
1214    * `gio move id1 ./id2/id1`) */
1215   op_done = g_file_move (source_file, dest_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error);
1216   g_assert_no_error (error);
1217   g_assert_true (op_done);
1218 
1219   /* TODO: Assert here that both the files are present */
1220 }
1221 #endif
1222 
1223 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Delete Test Case Functions  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1224 
1225 static void
gvfs_google_test_recursive_delete_test_dir_folder(gconstpointer user_data)1226 gvfs_google_test_recursive_delete_test_dir_folder (gconstpointer user_data)
1227 {
1228   GVfsGoogleTestData *self = (GVfsGoogleTestData *) user_data;
1229   gboolean op_done;
1230   g_autoptr(GError) error = NULL;
1231 
1232   op_done = delete_and_make_new_directory (self->test_dir, &error);
1233   g_assert_no_error (error);
1234   g_assert_true (op_done);
1235 }
1236 
1237 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Main Function  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1238 
1239 gint
main(gint argc,gchar * argv[])1240 main (gint argc, gchar *argv [])
1241 {
1242   gint retval = EXIT_SUCCESS;
1243   GVfsGoogleTestData *self;
1244   g_autoptr(GError) error = NULL;
1245 
1246   setlocale (LC_ALL, "");
1247 
1248   g_test_init (&argc, &argv, NULL);
1249 
1250   gvfs_google_test_init (&self, &error);
1251   if (error != NULL)
1252     {
1253       g_warning ("Error (init): %s", error->message);
1254       return 1;
1255     }
1256 
1257   /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Make Dir test cases  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1258 
1259   /* Test Scenario: We try to create a folder with its title set to the string
1260    * "valid_display_name_directory".
1261    *
1262    * Expected Behaviour: The newly created folder has the title
1263    * "valid_display_name_directory".
1264    *
1265    * Actual Behaviour is same as expected behaviour. */
1266   g_test_add_data_func ("/make_directory/using_valid_display_name",
1267                         (gconstpointer) self,
1268                         gvfs_google_test_make_directory_using_valid_display_name);
1269 
1270   /* Test Scenario: We try to create a folder having the title of the folder set
1271    * to some other file/folder's ID. So, we try to create a new folder with
1272    * self->test_dir_entry's ID.
1273    *
1274    * Expected Behaviour: The newly created folder has the same title as
1275    * self->test_dir_entry's ID.
1276    *
1277    * Actual Behaviour: The newly created folder gets its title set to
1278    * self->test_dir_entry's title and *NOT* its ID. The reason is well documented
1279    * in the make_directory function in gvfsbackendgoogle.c */
1280   g_test_add_data_func ("/make_directory/using_valid_id_of_other_directory",
1281                         (gconstpointer) self,
1282                         gvfs_google_test_make_directory_using_valid_id);
1283 
1284   /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Copy test cases  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1285 
1286   /* The below test case is equivalent to the following commandline operations:
1287    * (Assume that file with ID `id1` has the title $T)
1288    *
1289    * `gio copy id1 ./"$T (copy)"`           (where id2 is the ID of a folder)
1290    *
1291    * This operation mimics what nautilus does when we do a Ctrl+C & Ctrl+V
1292    * operation on a file inside same parent directory. It simply appends a
1293    * " (copy)" to the name of the file. */
1294   g_test_add_data_func ("/copy_file/within_same_parent_with_title_change",
1295                         (gconstpointer) self,
1296                         gvfs_google_test_copy_file_within_same_parent_with_title_change);
1297 
1298   /* We try to copy a file within the same parent without changing the title, i.e. this
1299    * operation corresponds to `gio copy -i ./file1_title ./file1_title` but without overwrite.
1300    *
1301    * This operation should supposedly fail with error code `G_IO_ERROR_EXISTS`
1302    * and string "Target file already exists". */
1303   g_test_add_data_func ("/copy_file/within_same_parent_with_same_title",
1304                         (gconstpointer) self,
1305                         gvfs_google_test_copy_file_within_same_parent_with_same_title);
1306 
1307   /* We try to copy a file within the same parent and keeping the title of file
1308    * to be same as the ID of source file, i.e. this operation corresponds to
1309    * `gio copy -i ./id1 ./id1` but without overwrite.
1310    *
1311    * This operation should supposedly fail with error code `G_IO_ERROR_EXISTS`
1312    * and string "Target file already exists". */
1313   g_test_add_data_func ("/copy_file/within_same_parent_with_source_id_as_destination_basename",
1314                         (gconstpointer) self,
1315                         gvfs_google_test_copy_file_within_same_parent_with_source_id_as_destination_basename);
1316 
1317   /* The below test case is equivalent to the following commandline operations:
1318    *
1319    * `gio copy ./id1 ./$Title$` where $Title$ is the title of file with ID `id1`.
1320    *
1321    * This operation should supposedly fail when done over the commandline gio
1322    * tool with error code `G_IO_ERROR_FAILED` and string "Operation Not Supported".
1323    * TODO: Fix the below test-case to use actual overwrite. */
1324   g_test_add_data_func ("/copy_file/within_same_parent_try_overwrite_with_same_title",
1325                         (gconstpointer) self,
1326                         gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_same_title);
1327 
1328   /* The below test case is equivalent to the following commandline operations:
1329    *
1330    * `gio copy id1 ./id1`
1331    *
1332    * This operation should supposedly fail when done over the commandline gio
1333    * tool with error code `G_IO_ERROR_FAILED` and string "Operation Not Supported".
1334    * TODO: Fix the below test-case to use actual overwrite. */
1335   g_test_add_data_func ("/copy_file/within_same_parent_try_overwrite_with_id",
1336                         (gconstpointer) self,
1337                         gvfs_google_test_copy_file_within_same_parent_try_overwrite_with_id);
1338 
1339   /* The below test case is equivalent to the following commandline operations:
1340    * `gio copy id1 id2/$Title$`  (where id2 is the ID of a folder, and $Title$
1341    * is the title of file with ID `id1`) */
1342   g_test_add_data_func ("/copy_file/from_one_parent_to_other_using_same_title",
1343                         (gconstpointer) self,
1344                         gvfs_google_test_copy_file_from_one_parent_to_other_using_same_title);
1345 
1346   /* The below test cases causes just a collision on the volatile entry. This
1347    * is because the previously executed test copies a file into the OP_COPY_TEST_DIRECTORY.
1348    * So, one volatile entry was already there because of that file, and we
1349    * change the title here to only cause a collision on the volatile entry (and
1350    * not the title too).
1351    *
1352    * It basically mimics the following case:
1353    * `gio copy id1 id2/some_title`
1354    * `gio copy id1 id2/some_random_title` */
1355   g_test_add_data_func ("/copy_file/from_one_parent_to_other_with_volatile_entry_collision_only",
1356                         (gconstpointer) self,
1357                         gvfs_google_test_copy_file_from_one_parent_to_other_with_volatile_entry_collision_only);
1358 
1359   /* The below test case uses the same function as the test case with
1360    * identifier "/copy_file/from_one_parent_to_other" because copying
1361    * file from source to destination is same as producing both kinds of
1362    * collisions at once.
1363    *
1364    * It basically mimics the following case:
1365    * `gio copy id1 id2/some_title`
1366    * `gio copy id1 id2/some_title`
1367    *
1368    * TODO: Re-enable the below test-case once you have orderBy="modifiedDate" */
1369 #ifdef HAVE_GDATA_DOCUMENTS_QUERY_SET_ORDER_BY
1370   g_test_add_data_func ("/copy_file/from_one_parent_to_other_with_both_title_and_volatile_entry_collision",
1371                         (gconstpointer) self,
1372                         gvfs_google_test_copy_file_from_one_parent_to_other_using_same_title);
1373 #endif
1374 
1375   /* The below test case is equivalent to the following commandline operations:
1376    * `gio copy id1 id2/id1`  (where id2 is the ID of a folder) */
1377   g_test_add_data_func ("/copy_file/from_one_parent_to_other_using_id",
1378                         (gconstpointer) self,
1379                         gvfs_google_test_copy_file_from_one_parent_to_other_using_id);
1380 
1381   /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Move test cases  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1382 
1383   /* The below test case is equivalent to the following commandline operations:
1384    * (Assume that file with ID `id1` has the title "title1")
1385    *
1386    * `gio move ./title1 ./title1`
1387    *
1388    * This operation will fail with an error */
1389   g_test_add_data_func ("/move_file/within_same_parent_without_title_change",
1390                         (gconstpointer) self,
1391                         gvfs_google_test_move_file_within_same_parent_without_title_change);
1392 
1393   /* The below test case is equivalent to the following commandline operations:
1394    * (Assume that file with ID `id1` has the title ${TITLE})
1395    *
1396    * `gio move ./${TITLE} ./SomeOtherTitle`
1397    *
1398    * This is just a normal rename operation in POSIX world, and the backend allows this. */
1399   g_test_add_data_func ("/move_file/within_same_parent_with_title_change",
1400                         (gconstpointer) self,
1401                         gvfs_google_test_move_file_within_same_parent_with_title_change);
1402 
1403   /* The below test case is equivalent to the following commandline operations:
1404    * `gio move ./id1 ./id2/$Title$` (where `id2` is the ID of a folder, and
1405    * $Title$ is the title of file with ID `id1`).
1406    *
1407    * This is simplest case for cross directory file moving. */
1408   g_test_add_data_func ("/move_file/from_one_parent_to_other_without_backup",
1409                         (gconstpointer) self,
1410                         gvfs_google_test_move_file_from_one_parent_to_other_without_backup);
1411 
1412   /* The below test case is equivalent to the following commandline operations
1413    * (with the G_FILE_COPY_BACKUP flag supplied to g_file_move function):
1414    * `gio move ./id1 id2/$Title$`  (where `id2` is the ID of a folder, and
1415    * $Title$ is the title of file with ID `id1`)
1416    *
1417    * Although the g_vfs_backend_google_move () will fail with G_IO_ERROR_NOT_SUPPORTED,
1418    * gio will use the fallback (copy + create + read + write + delete) to
1419    * support a backup operation. */
1420   g_test_add_data_func ("/move_file/from_one_parent_to_other_with_backup",
1421                         (gconstpointer) self,
1422                         gvfs_google_test_move_file_from_one_parent_to_other_with_backup);
1423 
1424   /* The below test case is equivalent to the following commandline operations:
1425    * `gio move ./id1 id2/$Title$`  (where `id2` is the ID of a folder, and
1426    * $Title$ is the title of file with ID `id1`) */
1427   g_test_add_data_func ("/move_file/from_one_parent_to_other_using_same_title",
1428                         (gconstpointer) self,
1429                         gvfs_google_test_move_file_from_one_parent_to_other_using_same_title);
1430 
1431   /* The below test case is equivalent to the following commandline operations:
1432    * `gio move ./id1 id2/SomeNewTitle`  (where `id2` is the ID of a folder, and
1433    * $Title$ is the title of file with ID `id1`) */
1434   g_test_add_data_func ("/move_file/from_one_parent_to_other_using_new_title",
1435                         (gconstpointer) self,
1436                         gvfs_google_test_move_file_from_one_parent_to_other_using_new_title);
1437 
1438   /* The below test case is equivalent to the following commandline operations:
1439    * `gio move ./id1 id2/id1`  (where `id2` is the ID of a folder) */
1440   g_test_add_data_func ("/move_file/from_one_parent_to_other_using_id",
1441                         (gconstpointer) self,
1442                         gvfs_google_test_move_file_from_one_parent_to_other_using_id);
1443 
1444   /* The below test case is equivalent to the following commandline operations:
1445    *
1446    * 1. `gio copy ./id1 ./id2/`                   ("id2" is the real ID of a folder)
1447    * 2. `gio move ./id1 ./id2/`
1448    *
1449    * In this, the copy operation will create a volatile entry i.e. (id1, id2) -> Entry tuple.
1450    * Later, during the move operation, this volatile entry will collide with
1451    * the real ID "id1". We support this operation and the below test should pass.
1452    * TODO: Re-enable the below test-case once you have orderBy="modifiedDate" */
1453 #ifdef HAVE_GDATA_DOCUMENTS_QUERY_SET_ORDER_BY
1454   g_test_add_data_func ("/move_file/from_one_parent_to_other_with_both_title_and_volatile_entry_collision",
1455                         (gconstpointer) self,
1456                         gvfs_google_test_move_file_from_one_parent_to_other_with_both_title_and_volatile_entry_collision);
1457 #endif
1458 
1459   /* ~~~~~~~~~~~~~~~~~~~~~~~~~~ Delete test cases  ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1460 
1461   /* We simply delete everything in the below case. If the backend crashes at
1462    * this point, there is some issue with cache. Moreover, delete is the case
1463    * which can be used to ensure the sanity of the cache. If delete wrongly
1464    * removes an entry (or wrongly decreases the ref_count), there's a very high
1465    * chance of getting a segfault sometime later.
1466    *
1467    * Also, beyond the execution of below test case, the GFile corresponding to
1468    * self->test_dummy_file won't be valid since that file will be deleted. As a result,
1469    * any operation done using test_dummy_file will result into an error. The memory
1470    * corresponding to the test_dummy_file GFile will be freed in the cleanup
1471    * function. */
1472   g_test_add_data_func ("/recursive_delete/test_dir_folder",
1473                         (gconstpointer) self,
1474                         gvfs_google_test_recursive_delete_test_dir_folder);
1475 
1476   retval = g_test_run ();
1477 
1478   gvfs_google_test_exit_cleanup (&self, &error);
1479   if (error != NULL)
1480     {
1481       g_warning ("Error (cleanup): %s", error->message);
1482       retval = EXIT_FAILURE;
1483     }
1484 
1485   return retval;
1486 }
1487