#include #include #include #include #include #include #include #include static void test_file_refcount_single_file (void) { g_assert_cmpint (nautilus_directory_number_outstanding (), ==, 0); NautilusFile *file = nautilus_file_get_by_uri ("file:///home/"); g_assert_cmpint (G_OBJECT (file)->ref_count, ==, 1); g_assert_cmpint (G_OBJECT (file->details->directory)->ref_count, ==, 1); g_assert_cmpint (nautilus_directory_number_outstanding (), ==, 1); nautilus_file_unref (file); g_assert_cmpint (nautilus_directory_number_outstanding (), ==, 0); } static void test_file_check_name_bland (void) { g_autoptr (NautilusFile) file = nautilus_file_get_by_uri ("file:///home"); const char *name = nautilus_file_get_name (file); g_assert_cmpstr (name, ==, "home"); } static void test_file_check_name_trailing_slash (void) { g_autoptr (NautilusFile) file = nautilus_file_get_by_uri ("file:///home/"); const char *name = nautilus_file_get_name (file); g_assert_cmpstr (name, ==, "home"); } static void test_file_duplicate_pointers (void) { g_autoptr (NautilusFile) file = nautilus_file_get_by_uri ("file:///home/"); g_assert_true (nautilus_file_get_by_uri ("file:///home/") == file); nautilus_file_unref (file); g_assert_true (nautilus_file_get_by_uri ("file:///home") == file); nautilus_file_unref (file); } static void test_file_sort_order (void) { g_autoptr (NautilusFile) file_1 = nautilus_file_get_by_uri ("file:///etc"); g_autoptr (NautilusFile) file_2 = nautilus_file_get_by_uri ("file:///usr"); NautilusFileSortType sort_type = NAUTILUS_FILE_SORT_BY_DISPLAY_NAME; g_assert_cmpint (G_OBJECT (file_1)->ref_count, ==, 1); g_assert_cmpint (G_OBJECT (file_2)->ref_count, ==, 1); int order = nautilus_file_compare_for_sort (file_1, file_2, sort_type, FALSE, FALSE); g_assert_cmpint (order, <, 0); int order_reversed = nautilus_file_compare_for_sort (file_1, file_2, sort_type, FALSE, TRUE); g_assert_cmpint (order_reversed, >, 0); } static void test_file_sort_with_self (void) { g_autoptr (NautilusFile) file_1 = nautilus_file_get_by_uri ("file:///etc"); NautilusFileSortType sort_type = NAUTILUS_FILE_SORT_BY_DISPLAY_NAME; int order; order = nautilus_file_compare_for_sort (file_1, file_1, sort_type, TRUE, TRUE); g_assert_cmpint (order, ==, 0); order = nautilus_file_compare_for_sort (file_1, file_1, sort_type, TRUE, FALSE); g_assert_cmpint (order, ==, 0); order = nautilus_file_compare_for_sort (file_1, file_1, sort_type, FALSE, TRUE); g_assert_cmpint (order, ==, 0); order = nautilus_file_compare_for_sort (file_1, file_1, sort_type, FALSE, FALSE); g_assert_cmpint (order, ==, 0); } typedef struct { const gsize len; GStrv expected_names; GStrv expected_content; gboolean *success; } NautilusFileBatchRenameTestData; static void batch_rename_callback (NautilusFile *file, GFile *result_location, GError *error, gpointer callback_data) { NautilusFileBatchRenameTestData *data = callback_data; g_autoptr (GStrvBuilder) name_builder = g_strv_builder_new (); g_autoptr (GStrvBuilder) content_builder = g_strv_builder_new (); g_auto (GStrv) result_names = NULL, result_content = NULL; g_assert_no_error (error); g_assert_cmpint (data->len, ==, g_strv_length (data->expected_names)); g_assert_cmpint (data->len, ==, g_strv_length (data->expected_content)); for (guint i = 0; i < data->len; i++) { g_autoptr (GFile) location = g_file_new_build_filename (test_get_tmp_dir (), data->expected_names[i], NULL); g_autoptr (GFileInfo) info = g_file_query_info (location, NAUTILUS_FILE_DEFAULT_ATTRIBUTES, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_autoptr (GFileInputStream) stream = g_file_read (location, NULL, NULL); gchar content[1024]; g_assert_nonnull (stream); g_assert_true (g_input_stream_read_all (G_INPUT_STREAM (stream), content, sizeof (content), NULL, NULL, NULL)); g_assert_true (g_input_stream_close (G_INPUT_STREAM (stream), NULL, NULL)); g_strv_builder_add (name_builder, g_file_info_get_display_name (info)); g_strv_builder_add (content_builder, content); } result_names = g_strv_builder_end (name_builder); result_content = g_strv_builder_end (content_builder); for (guint i = 0; i < data->len; i++) { g_autofree gchar *expected_name = g_path_get_basename (data->expected_names[i]); g_autofree gchar *expected_content = g_path_get_basename (data->expected_content[i]); g_assert_cmpstr (result_names[i], ==, expected_name); g_assert_cmpstr (result_content[i], ==, expected_content); } *data->success = TRUE; } static void batch_rename_test (const GStrv hierarchy, const GStrv original_names, const GStrv expected_names) { g_autolist (NautilusFile) files = NULL; g_autolist (GString) new_names = NULL; const gsize len = g_strv_length (expected_names); gboolean success = FALSE; NautilusFileBatchRenameTestData data = { len, expected_names, original_names, &success }; file_hierarchy_create (hierarchy, ""); for (gint i = len - 1; i >= 0; i--) { g_autoptr (GFile) location = g_file_new_build_filename (test_get_tmp_dir (), original_names[i], NULL); NautilusFile *file = nautilus_file_get (location); GString *new_name = g_string_new_take (g_path_get_basename (expected_names[i])); files = g_list_prepend (files, file); new_names = g_list_prepend (new_names, new_name); } nautilus_file_batch_rename (files, new_names, batch_rename_callback, &data); g_assert_true (success); /* Test undo by changing the expected names */ data.expected_names = original_names; success = FALSE; test_operation_undo (); batch_rename_callback (NULL, NULL, NULL, &data); g_assert_true (success); test_clear_tmp_dir (); } static void test_file_batch_rename_cycles (void) { char *test_cases[][2][10] = { /* Small cycle */ {{"file_1", "file_2", NULL}, {"file_2", "file_1", NULL}}, /* Medium cycle */ {{"file_1", "file_2", "file_3", "file_4", "file_5", "file_6", "file_7", "file_8", "file_9", NULL}, {"file_9", "file_1", "file_2", "file_3", "file_4", "file_5", "file_6", "file_7", "file_8", NULL}}, /* Multi-cycle */ {{"file_1", "file_2", "file_3", "file_4", "file_5", "file_6", "file_7", "file_8", NULL}, {"file_8", "file_3", "file_4", "file_5", "file_6", "file_7", "file_2", "file_1", NULL}}, }; g_test_bug ("https://gitlab.gnome.org/GNOME/nautilus/-/issues/1443"); for (guint i = 0; i < G_N_ELEMENTS (test_cases); i++) { batch_rename_test (test_cases[i][0], test_cases[i][0], test_cases[i][1]); } } static void test_file_batch_rename_chains (void) { char *test_cases[][2][10] = { /* Medium chain */ {{"file_1", "file_2", "file_3", "file_4", "file_5", "file_6", "file_7", "file_8", "file_9", NULL}, {"file_2", "file_3", "file_4", "file_5", "file_6", "file_7", "file_8", "file_9", "file_10", NULL}}, }; for (guint i = 0; i < G_N_ELEMENTS (test_cases); i++) { batch_rename_test (test_cases[i][0], test_cases[i][0], test_cases[i][1]); } } static void test_file_batch_rename_replace (void) { char *test_cases[][2][10] = { /* File Extension replacement */ {{ "file_1.jpg", "file_2.jpeg", "file_3.gif", "file_4.png", "file_5.webm", "file_6.avif", "file_7.jxl", "file_8.jpeg", "file_9.bmp", NULL }, { "file_1.jpg", "file_2.jpg", "file_3.gif", "file_4.png", "file_5.webm", "file_6.avif", "file_7.jxl", "file_8.jpg", "file_9.bmp", NULL }}, }; for (guint i = 0; i < G_N_ELEMENTS (test_cases); i++) { batch_rename_test (test_cases[i][0], test_cases[i][0], test_cases[i][1]); } } static void test_file_batch_rename_different_folders (void) { char *hierarchy[] = { "folder1" G_DIR_SEPARATOR_S, "folder1" G_DIR_SEPARATOR_S "file_1", "folder2" G_DIR_SEPARATOR_S, "folder2" G_DIR_SEPARATOR_S "file_1", NULL }; char *test_cases[][2][3] = { /* Rename to the same name but in different folders */ {{ "folder1" G_DIR_SEPARATOR_S "file_1", "folder2" G_DIR_SEPARATOR_S "file_1", NULL }, { "folder1" G_DIR_SEPARATOR_S "file_2", "folder2" G_DIR_SEPARATOR_S "file_2", NULL }}, }; for (guint i = 0; i < G_N_ELEMENTS (test_cases); i++) { batch_rename_test (hierarchy, test_cases[i][0], test_cases[i][1]); } } static void test_file_permissions_can_set (void) { g_autoptr (GFile) location = g_file_new_build_filename (test_get_tmp_dir (), "perm_test_file", NULL); g_autoptr (GFileOutputStream) stream = g_file_create (location, G_FILE_CREATE_NONE, NULL, NULL); gint mode = 0600; g_assert_nonnull (stream); g_assert_true (g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL)); g_assert_true (g_file_set_attribute_uint32 (location, G_FILE_ATTRIBUTE_UNIX_MODE, mode, G_FILE_QUERY_INFO_NONE, NULL, NULL)); g_autoptr (NautilusFile) file = nautilus_file_get (location); file_load_attributes (file, NAUTILUS_ATTRIBUTE_INFO); g_assert_true (nautilus_file_can_set_permissions (file)); test_clear_tmp_dir (); } typedef struct { NautilusFile *file; gboolean done; } PermissionTestData; static void file_changed_set_cb (NautilusFile *file, gboolean *done) { *done = TRUE; } static void permissions_success_cb (NautilusFile *file, GFile *result_location, GError *error, gpointer user_data) { PermissionTestData *perm_data = user_data; g_assert_no_error (error); g_assert_true (file == perm_data->file); perm_data->done = TRUE; } static void test_file_permissions_set_basic (void) { g_autoptr (GFile) location = g_file_new_build_filename (test_get_tmp_dir (), "perm_test_file", NULL); g_autoptr (GFileOutputStream) stream = g_file_create (location, G_FILE_CREATE_NONE, NULL, NULL); g_assert_nonnull (stream); g_assert_true (g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL)); g_autoptr (NautilusFile) file = nautilus_file_get (location); PermissionTestData perm_data = { file, FALSE }; gboolean file_changed = FALSE; guint32 perms = 0600; file_load_attributes (file, NAUTILUS_ATTRIBUTE_INFO); g_signal_connect (file, "changed", G_CALLBACK (file_changed_set_cb), &file_changed); nautilus_file_set_permissions (file, perms, permissions_success_cb, &perm_data); ITER_CONTEXT_WHILE (!perm_data.done); g_autoptr (GFileInfo) info = g_file_query_info (location, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_assert_nonnull (info); g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE)); guint32 mode = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE); g_assert_cmphex (mode & 0777, ==, perms); g_assert_true (file_changed); test_clear_tmp_dir (); } static void test_file_permissions_set_same (void) { g_autoptr (GFile) location = g_file_new_build_filename (test_get_tmp_dir (), "perm_test_file", NULL); g_autoptr (GFileOutputStream) stream = g_file_create (location, G_FILE_CREATE_NONE, NULL, NULL); g_assert_nonnull (stream); g_assert_true (g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL)); g_autoptr (NautilusFile) file = nautilus_file_get (location); gboolean file_changed = FALSE; g_autoptr (GFileInfo) info_before = g_file_query_info (location, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NONE, NULL, NULL); guint32 mode_before = g_file_info_get_attribute_uint32 (info_before, G_FILE_ATTRIBUTE_UNIX_MODE); PermissionTestData perm_data = { file, FALSE }; file_load_attributes (file, NAUTILUS_ATTRIBUTE_INFO); g_signal_connect (file, "changed", G_CALLBACK (file_changed_set_cb), &file_changed); nautilus_file_set_permissions (file, mode_before, permissions_success_cb, &perm_data); ITER_CONTEXT_WHILE (!perm_data.done); g_autoptr (GFileInfo) info_after = g_file_query_info (location, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_assert_nonnull (info_after); g_assert_true (g_file_info_has_attribute (info_after, G_FILE_ATTRIBUTE_UNIX_MODE)); guint32 mode_after = g_file_info_get_attribute_uint32 (info_after, G_FILE_ATTRIBUTE_UNIX_MODE); g_assert_cmphex (mode_after, ==, mode_before); g_assert_false (file_changed); test_clear_tmp_dir (); } static void test_directory_counts (void) { const GStrv deep_hierarchy = (char *[]) { "deepcount/", "deepcount/file1", "deepcount/dir1/", "deepcount/dir1/file2", "deepcount/dir1/dir1a/", "deepcount/dir1/dir1a/file3", "deepcount/dir2/", "deepcount/dir2/file4", NULL }; g_autoptr (GFile) location = g_file_new_build_filename (test_get_tmp_dir (), "deepcount", NULL); g_autoptr (NautilusFile) file = nautilus_file_get (location); guint dir_count = 0, file_count = 0, unreadable = 0, item_count = 0; NautilusRequestStatus status; gboolean count_unreadable = TRUE; file_hierarchy_create (deep_hierarchy, ""); file_load_attributes (file, NAUTILUS_ATTRIBUTE_INFO | NAUTILUS_ATTRIBUTE_DIRECTORY_ITEM_COUNT | NAUTILUS_ATTRIBUTE_DEEP_COUNT); g_assert_true (nautilus_file_get_directory_item_count (file, &item_count, &count_unreadable)); g_assert_cmpint (item_count, ==, 3); g_assert_false (count_unreadable); status = nautilus_file_get_deep_counts (file, &dir_count, &file_count, &unreadable, NULL, TRUE); g_assert_cmpint (status, ==, NAUTILUS_REQUEST_DONE); g_assert_cmpint (dir_count, ==, 3); g_assert_cmpint (file_count, ==, 4); g_assert_cmpint (unreadable, ==, 0); test_clear_tmp_dir (); } int main (int argc, char *argv[]) { g_autoptr (NautilusFileUndoManager) undo_manager = NULL; g_test_init (&argc, &argv, NULL); g_test_set_nonfatal_assertions (); nautilus_ensure_extension_points (); undo_manager = nautilus_file_undo_manager_new (); g_test_add_func ("/file-refcount/single-file", test_file_refcount_single_file); g_test_add_func ("/file-check-name/bland", test_file_check_name_bland); g_test_add_func ("/file-check-name/trailing-slash", test_file_check_name_trailing_slash); g_test_add_func ("/file-duplicate-pointers/1.0", test_file_duplicate_pointers); g_test_add_func ("/file-sort/order", test_file_sort_order); g_test_add_func ("/file-sort/with-self", test_file_sort_with_self); g_test_add_func ("/file-batch-rename/cycles", test_file_batch_rename_cycles); g_test_add_func ("/file-batch-rename/chains", test_file_batch_rename_chains); g_test_add_func ("/file-batch-rename/replace", test_file_batch_rename_replace); g_test_add_func ("/file-batch-rename/different-folders", test_file_batch_rename_different_folders); g_test_add_func ("/file/permissions/can_set", test_file_permissions_can_set); g_test_add_func ("/file/permissions/basic", test_file_permissions_set_basic); g_test_add_func ("/file/permissions/same", test_file_permissions_set_same); g_test_add_func ("/file/deep-counts/basic", test_directory_counts); return g_test_run (); }