#include <stic.h> #include <unistd.h> /* rmdir() unlink() */ #include <stdio.h> /* fclose() fopen() fprintf() */ #include <string.h> /* strcpy() */ #include <test-utils.h> #include "../../src/cfg/config.h" #include "../../src/compat/fs_limits.h" #include "../../src/compat/os.h" #include "../../src/int/fuse.h" #include "../../src/modes/dialogs/msg_dialog.h" #include "../../src/ui/ui.h" #include "../../src/utils/fs.h" #include "../../src/utils/path.h" #include "../../src/utils/str.h" #include "../../src/filelist.h" #include "../../src/status.h" static char *saved_cwd; static void populate(view_t *view); static void mount(view_t *view, const char cmd[]); static int unmount(view_t *view); static int mounter_error_dlg_cb(const char type[], const char title[], const char message[]); static int failed_mount_dlg_cb(const char type[], const char title[], const char message[]); static int can_fuse(void); static int can_fuse_and_emulate_errors(void); SETUP() { curr_view = &lwin; other_view = &rwin; view_setup(&lwin); view_setup(&rwin); char cwd[PATH_MAX + 1]; assert_true(get_cwd(cwd, sizeof(cwd)) == cwd); make_abs_path(lwin.curr_dir, sizeof(lwin.curr_dir), SANDBOX_PATH, "", cwd); strcpy(rwin.curr_dir, lwin.curr_dir); char fuse_home[PATH_MAX + 1]; make_abs_path(fuse_home, sizeof(fuse_home), SANDBOX_PATH, ".fuse", cwd); replace_string(&cfg.fuse_home, fuse_home); replace_string(&cfg.shell, "/bin/sh"); replace_string(&cfg.slow_fs_list, ""); curr_stats.fuse_umount_cmd = "true"; saved_cwd = save_cwd(); } TEARDOWN() { fuse_unmount_all(); assert_success(rmdir(cfg.fuse_home)); view_teardown(&lwin); view_teardown(&rwin); update_string(&cfg.fuse_home, NULL); update_string(&cfg.shell, NULL); update_string(&cfg.slow_fs_list, NULL); curr_stats.fuse_umount_cmd = NULL; restore_cwd(saved_cwd); } TEST(bad_mounter_is_handled, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); dlg_set_callback(&failed_mount_dlg_cb); mount(&lwin, "FUSE_MOUNT|false"); assert_false(fuse_is_mount_point(lwin.curr_dir)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(fuse_mount_works, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); char path[PATH_MAX + 1]; snprintf(path, sizeof(path), "%s/test", lwin.curr_dir); create_file(path); assert_int_equal(1, unmount(&lwin)); assert_success(unlink(SANDBOX_PATH "/mount.me/test")); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(fuse_mount_2_works, IF(can_fuse)) { FILE *const f = fopen(SANDBOX_PATH "/mount.spec", "w"); fprintf(f, "%s/mount.me", lwin.curr_dir); fclose(f); populate(&lwin); os_mkdir(SANDBOX_PATH "/mount.me", 0777); mount(&lwin, "FUSE_MOUNT2|rmdir %DESTINATION_DIR && " "ln -s %PARAM %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); char path[PATH_MAX + 1]; snprintf(path, sizeof(path), "%s/test", lwin.curr_dir); create_file(path); assert_int_equal(1, unmount(&lwin)); assert_success(unlink(SANDBOX_PATH "/mount.me/test")); assert_success(rmdir(SANDBOX_PATH "/mount.me")); assert_success(unlink(SANDBOX_PATH "/mount.spec")); } TEST(fuse_mount_2_fails_on_nonexistent_file, IF(can_fuse)) { create_file(SANDBOX_PATH "/mount.spec"); populate(&lwin); assert_success(unlink(SANDBOX_PATH "/mount.spec")); os_mkdir(SANDBOX_PATH "/mount.me", 0777); mount(&lwin, "FUSE_MOUNT2|rmdir %DESTINATION_DIR && " "ln -s %PARAM %DESTINATION_DIR"); assert_false(fuse_is_mount_point(lwin.curr_dir)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(fuse_mount_2_fails_on_empty_file, IF(can_fuse)) { create_file(SANDBOX_PATH "/mount.spec"); populate(&lwin); os_mkdir(SANDBOX_PATH "/mount.me", 0777); mount(&lwin, "FUSE_MOUNT2|rmdir %DESTINATION_DIR && " "ln -s %PARAM %DESTINATION_DIR"); assert_false(fuse_is_mount_point(lwin.curr_dir)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); assert_success(unlink(SANDBOX_PATH "/mount.spec")); } TEST(fuse_mount_2_fails_on_file_with_newline_only, IF(can_fuse)) { FILE *const f = fopen(SANDBOX_PATH "/mount.spec", "w"); fputs("\n", f); fclose(f); populate(&lwin); os_mkdir(SANDBOX_PATH "/mount.me", 0777); mount(&lwin, "FUSE_MOUNT2|rmdir %DESTINATION_DIR && " "ln -s %PARAM %DESTINATION_DIR"); assert_false(fuse_is_mount_point(lwin.curr_dir)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); assert_success(unlink(SANDBOX_PATH "/mount.spec")); } TEST(fuse_mount_3_works, IF(can_fuse)) { curr_stats.fuse_umount_cmd = "false"; os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); mount(&lwin, "FUSE_MOUNT3|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); char path[PATH_MAX + 1]; snprintf(path, sizeof(path), "%s/test", lwin.curr_dir); create_file(path); assert_int_equal(1, unmount(&lwin)); assert_success(unlink(SANDBOX_PATH "/mount.me/test")); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(multiple_mounts_work, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); os_mkdir(SANDBOX_PATH "/mount.me.too", 0777); populate(&rwin); rwin.list_pos = 2; assert_string_equal("mount.me.too", rwin.dir_entry[2].name); mount(&rwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(rwin.curr_dir)); /* Checks that initial mount is still reported correctly. */ assert_true(fuse_is_mount_point(lwin.curr_dir)); /* Try unmounting in original order (mounts are stored in reverse order). */ assert_int_equal(1, unmount(&lwin)); assert_int_equal(1, unmount(&rwin)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); assert_success(rmdir(SANDBOX_PATH "/mount.me.too")); } TEST(unmounting_failure_is_handled, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); char path[PATH_MAX + 1]; snprintf(path, sizeof(path), "%s/test", lwin.curr_dir); create_file(path); curr_stats.fuse_umount_cmd = "false"; assert_int_equal(-1, unmount(&lwin)); assert_true(fuse_is_mount_point(lwin.curr_dir)); curr_stats.fuse_umount_cmd = "true"; assert_int_equal(1, unmount(&lwin)); assert_false(fuse_is_mount_point(lwin.curr_dir)); assert_success(unlink(SANDBOX_PATH "/mount.me/test")); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(can_unmount_all_mounts, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); os_mkdir(SANDBOX_PATH "/mount.me.too", 0777); populate(&rwin); rwin.list_pos = 2; assert_string_equal("mount.me.too", rwin.dir_entry[2].name); mount(&rwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(rwin.curr_dir)); fuse_unmount_all(); restore_cwd(saved_cwd); saved_cwd = save_cwd(); assert_false(fuse_is_mount_point(lwin.curr_dir)); assert_false(fuse_is_mount_point(rwin.curr_dir)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); assert_success(rmdir(SANDBOX_PATH "/mount.me.too")); } TEST(nested_mount_is_possible, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); os_mkdir(SANDBOX_PATH "/mount.me/nested.mount", 0777); populate(&lwin); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); char path[PATH_MAX + 1]; snprintf(path, sizeof(path), "%s/test", lwin.curr_dir); create_file(path); assert_int_equal(1, unmount(&lwin)); assert_int_equal(1, unmount(&lwin)); assert_success(unlink(SANDBOX_PATH "/mount.me/nested.mount/test")); assert_success(rmdir(SANDBOX_PATH "/mount.me/nested.mount")); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(mounts_are_reused, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); populate(&rwin); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); mount(&rwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(rwin.curr_dir)); assert_true(paths_are_equal(lwin.curr_dir, rwin.curr_dir)); assert_int_equal(1, unmount(&lwin)); assert_int_equal(0, unmount(&rwin)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(updir_from_a_mount, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); populate(&rwin); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); mount(&rwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(rwin.curr_dir)); assert_true(fuse_try_updir_from_a_mount(lwin.curr_dir, &lwin)); assert_false(paths_are_equal(lwin.curr_dir, rwin.curr_dir)); assert_int_equal(0, unmount(&lwin)); assert_int_equal(1, unmount(&rwin)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(mounting_with_foreground_flag_works, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR %FOREGROUND"); assert_true(fuse_is_mount_point(lwin.curr_dir)); char path[PATH_MAX + 1]; snprintf(path, sizeof(path), "%s/test", lwin.curr_dir); create_file(path); assert_int_equal(1, unmount(&lwin)); assert_success(unlink(SANDBOX_PATH "/mount.me/test")); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(fuse_get_mount_file_works, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); char full_path[PATH_MAX + 1]; get_current_full_path(&lwin, sizeof(full_path), full_path); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_true(fuse_is_mount_point(lwin.curr_dir)); assert_true(paths_are_equal(full_path, fuse_get_mount_file(lwin.curr_dir))); char nested[PATH_MAX + 1]; snprintf(nested, sizeof(nested), "%s/nested", lwin.curr_dir); assert_true(paths_are_equal(full_path, fuse_get_mount_file(nested))); assert_int_equal(1, unmount(&lwin)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(multiline_errors_are_handled, IF(can_fuse)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); dlg_set_callback(&mounter_error_dlg_cb); mount(&lwin, "FUSE_MOUNT|echo first 1>&2 &&echo second 1>&2 &&exit 1"); assert_false(fuse_is_mount_point(lwin.curr_dir)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); } TEST(bad_fuse_home_is_handled, IF(can_fuse_and_emulate_errors)) { os_mkdir(SANDBOX_PATH "/mount.me", 0777); populate(&lwin); char fuse_home[PATH_MAX + 1]; make_abs_path(fuse_home, sizeof(fuse_home), SANDBOX_PATH, "for/fuse", saved_cwd); replace_string(&cfg.fuse_home, fuse_home); os_mkdir(SANDBOX_PATH "/for", 0555); mount(&lwin, "FUSE_MOUNT|rmdir %DESTINATION_DIR && " "ln -s %SOURCE_FILE %DESTINATION_DIR"); assert_false(fuse_is_mount_point(lwin.curr_dir)); assert_success(os_chmod(SANDBOX_PATH "/for", 0777)); assert_success(rmdir(SANDBOX_PATH "/mount.me")); make_abs_path(fuse_home, sizeof(fuse_home), SANDBOX_PATH, "for", saved_cwd); replace_string(&cfg.fuse_home, fuse_home); } static void populate(view_t *view) { populate_dir_list(view, 0); restore_cwd(saved_cwd); saved_cwd = save_cwd(); } static void mount(view_t *view, const char cmd[]) { fuse_try_mount(view, cmd); restore_cwd(saved_cwd); saved_cwd = save_cwd(); } static int unmount(view_t *view) { int result = fuse_try_unmount(view); restore_cwd(saved_cwd); saved_cwd = save_cwd(); return result; } static int mounter_error_dlg_cb(const char type[], const char title[], const char message[]) { assert_string_equal("error", type); assert_string_equal("FUSE Mounter Errors", title); assert_string_equal("first\nsecond", message); dlg_set_callback(&failed_mount_dlg_cb); return 0; } static int failed_mount_dlg_cb(const char type[], const char title[], const char message[]) { assert_string_equal("error", type); assert_string_equal("FUSE", title); assert_string_starts_with("Failed to mount file: ", message); assert_string_ends_with("mount.me", message); dlg_set_callback(NULL); return 0; } static int can_fuse(void) { #if !defined(_WIN32) && !defined(__APPLE__) // These tests fail in a weird way on OS X... Failed to figure out why. return 1; #else return 0; #endif } static int can_fuse_and_emulate_errors(void) { return (can_fuse() && regular_unix_user()); } /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set cinoptions+=t0 : */