summaryrefslogtreecommitdiff
path: root/tests/test_trash.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_trash.c')
-rw-r--r--tests/test_trash.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/tests/test_trash.c b/tests/test_trash.c
new file mode 100644
index 0000000..5138bd6
--- /dev/null
+++ b/tests/test_trash.c
@@ -0,0 +1,180 @@
+/*:*
+ * ggaze — trash unit test
+ *
+ * Exercises the ./Trash bin: bin (lazy create + collision suffix), restore
+ * (undo), permanent delete, and can_undo. Uses temp dirs; no display.
+ *
+ * Copyright (c) 2026 ggaze contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *:*/
+
+#include "trash.h"
+
+#include <gio/gio.h>
+#include <glib.h>
+
+static char *
+make_temp_dir(void) {
+ GError *p_err = NULL;
+ char *c_dir = g_dir_make_tmp("ggaze-trash-XXXXXX", &p_err);
+ g_assert_no_error(p_err);
+ return (c_dir);
+}
+
+static GFile *
+write_file(const char *c_dir, const char *c_name) {
+ char *c_path = g_build_filename(c_dir, c_name, NULL);
+ GFile *p_file = g_file_new_for_path(c_path);
+ GError *p_err = NULL;
+ g_file_replace_contents(p_file, "x", 1, NULL, FALSE,
+ G_FILE_CREATE_REPLACE_DESTINATION, NULL, NULL,
+ &p_err);
+ g_assert_no_error(p_err);
+ g_free(c_path);
+ return (p_file);
+}
+
+static void
+cleanup_temp_dir(char *c_dir) {
+ GFile *p_dir = g_file_new_for_path(c_dir);
+ GFileEnumerator *p_e =
+ g_file_enumerate_children(p_dir, "standard::name,standard::type",
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ if (p_e != NULL) {
+ GFileInfo *p_info;
+ while ((p_info = g_file_enumerator_next_file(p_e, NULL, NULL)) != NULL) {
+ GFile *p_child = g_file_get_child(p_dir, g_file_info_get_name(p_info));
+ if (g_file_info_get_file_type(p_info) == G_FILE_TYPE_DIRECTORY) {
+ /* recursively clean a subdir (.Trash) */
+ GFileEnumerator *p_e2 = g_file_enumerate_children(
+ p_child, "standard::name", G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ if (p_e2 != NULL) {
+ GFileInfo *p_i2;
+ while ((p_i2 = g_file_enumerator_next_file(p_e2, NULL, NULL)) !=
+ NULL) {
+ GFile *p_c2 =
+ g_file_get_child(p_child, g_file_info_get_name(p_i2));
+ g_file_delete(p_c2, NULL, NULL);
+ g_object_unref(p_c2);
+ g_object_unref(p_i2);
+ }
+ g_object_unref(p_e2);
+ }
+ }
+ g_file_delete(p_child, NULL, NULL);
+ g_object_unref(p_child);
+ g_object_unref(p_info);
+ }
+ g_object_unref(p_e);
+ }
+ g_file_delete(p_dir, NULL, NULL);
+ g_object_unref(p_dir);
+ g_free(c_dir);
+}
+
+static void
+test_bin_and_restore(void) {
+ char *c_dir = make_temp_dir();
+ GFile *p_a = write_file(c_dir, "a.jpg");
+ GFile *p_b = write_file(c_dir, "b.jpg");
+ GFile *p_dirf = g_file_new_for_path(c_dir);
+
+ Trash *p_t = trash_new(p_dirf);
+ GError *p_err = NULL;
+
+ /* Bin a.jpg → moves to .Trash/a.jpg. */
+ g_assert_true(trash_bin(p_t, p_a, &p_err));
+ g_assert_no_error(p_err);
+ g_assert_false(g_file_query_exists(p_a, NULL)); /* gone from dir */
+ g_assert_true(trash_can_undo(p_t));
+
+ /* Restore → a.jpg back at original. */
+ g_assert_true(trash_restore_last(p_t, &p_err));
+ g_assert_no_error(p_err);
+ g_assert_true(g_file_query_exists(p_a, NULL));
+ g_assert_false(trash_can_undo(p_t));
+
+ trash_delete(p_t);
+ g_object_unref(p_a);
+ g_object_unref(p_b);
+ g_object_unref(p_dirf);
+ cleanup_temp_dir(c_dir);
+}
+
+static void
+test_collision_suffix(void) {
+ char *c_dir = make_temp_dir();
+ GFile *p_a1 = write_file(c_dir, "img.jpg");
+ GFile *p_a2 = write_file(c_dir, "img-1.jpg");
+ GFile *p_dirf = g_file_new_for_path(c_dir);
+
+ Trash *p_t = trash_new(p_dirf);
+ GError *p_err = NULL;
+
+ /* Bin img.jpg → .Trash/img.jpg. */
+ g_assert_true(trash_bin(p_t, p_a1, &p_err));
+ g_assert_no_error(p_err);
+
+ /* Bin img-1.jpg → .Trash/img-1.jpg (no collision yet). */
+ g_assert_true(trash_bin(p_t, p_a2, &p_err));
+ g_assert_no_error(p_err);
+
+ /* Re-create img.jpg and bin it → .Trash/img-1.jpg would collide? No,
+ * img.jpg was already binned. Create a new img.jpg and bin → collision
+ * → .Trash/img-1.jpg (suffix). */
+ GFile *p_a3 = write_file(c_dir, "img.jpg");
+ g_assert_true(trash_bin(p_t, p_a3, &p_err));
+ g_assert_no_error(p_err);
+
+ /* Verify .Trash has 3 files. */
+ GFile *p_td = g_file_get_child(p_dirf, ".Trash");
+ GFileEnumerator *p_e = g_file_enumerate_children(
+ p_td, "standard::name", G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ guint u_count = 0;
+ if (p_e != NULL) {
+ GFileInfo *p_info;
+ while ((p_info = g_file_enumerator_next_file(p_e, NULL, NULL)) != NULL) {
+ u_count++;
+ g_object_unref(p_info);
+ }
+ g_object_unref(p_e);
+ }
+ g_assert_cmpint(u_count, ==, 3);
+ g_object_unref(p_td);
+ g_object_unref(p_a3);
+
+ trash_delete(p_t);
+ g_object_unref(p_a1);
+ g_object_unref(p_a2);
+ g_object_unref(p_dirf);
+ cleanup_temp_dir(c_dir);
+}
+
+static void
+test_permanent_delete(void) {
+ char *c_dir = make_temp_dir();
+ GFile *p_a = write_file(c_dir, "a.jpg");
+ GFile *p_dirf = g_file_new_for_path(c_dir);
+
+ Trash *p_t = trash_new(p_dirf);
+ GError *p_err = NULL;
+
+ g_assert_true(trash_permanently_delete(p_t, p_a, &p_err));
+ g_assert_no_error(p_err);
+ g_assert_false(g_file_query_exists(p_a, NULL));
+ g_assert_false(trash_can_undo(p_t)); /* permanent delete is not undoable */
+
+ trash_delete(p_t);
+ g_object_unref(p_a);
+ g_object_unref(p_dirf);
+ cleanup_temp_dir(c_dir);
+}
+
+int
+main(int i_argc, char **c_argv) {
+ g_test_init(&i_argc, &c_argv, NULL);
+ g_test_add_func("/trash/bin_and_restore", test_bin_and_restore);
+ g_test_add_func("/trash/collision_suffix", test_collision_suffix);
+ g_test_add_func("/trash/permanent_delete", test_permanent_delete);
+ return (g_test_run());
+} \ No newline at end of file