#include <stic.h> #include <unistd.h> /* chdir() rmdir() unlink() */ #include <limits.h> /* INT_MAX */ #include <stdio.h> /* remove() snprintf() */ #include <string.h> /* strcpy() strdup() */ #include <test-utils.h> #include "../../src/cfg/config.h" #include "../../src/compat/fs_limits.h" #include "../../src/compat/os.h" #include "../../src/engine/keys.h" #include "../../src/lua/vlua.h" #include "../../src/modes/menu.h" #include "../../src/modes/modes.h" #include "../../src/ui/statusbar.h" #include "../../src/ui/ui.h" #include "../../src/utils/dynarray.h" #include "../../src/utils/fs.h" #include "../../src/utils/macros.h" #include "../../src/utils/path.h" #include "../../src/utils/str.h" #include "../../src/utils/string_array.h" #include "../../src/cmd_core.h" #include "../../src/compare.h" #include "../../src/filelist.h" #include "../../src/flist_hist.h" #include "../../src/plugins.h" #include "../../src/registers.h" #include "../../src/running.h" #include "../../src/status.h" #include "../lua/asserts.h" static char *saved_cwd; static char cwd[PATH_MAX + 1]; static char sandbox[PATH_MAX + 1]; static char test_data[PATH_MAX + 1]; static void strings_list_is(const strlist_t expected, const strlist_t actual); SETUP_ONCE() { cfg.sizefmt.base = 1; assert_non_null(get_cwd(cwd, sizeof(cwd))); make_abs_path(sandbox, sizeof(sandbox), SANDBOX_PATH, "", cwd); make_abs_path(test_data, sizeof(test_data), TEST_DATA_PATH, "", cwd); } SETUP() { view_setup(&lwin); view_setup(&rwin); curr_view = &lwin; other_view = &rwin; conf_setup(); undo_setup(); cmds_init(); saved_cwd = save_cwd(); } TEARDOWN() { restore_cwd(saved_cwd); view_teardown(&lwin); view_teardown(&rwin); conf_teardown(); vle_cmds_reset(); undo_teardown(); } TEST(cd_in_root_works) { assert_success(chdir(test_data)); strcpy(lwin.curr_dir, test_data); assert_false(is_root_dir(lwin.curr_dir)); assert_success(cmds_dispatch("cd /", &lwin, CIT_COMMAND)); assert_true(is_root_dir(lwin.curr_dir)); } TEST(double_cd_uses_same_base_for_rel_paths) { char path[PATH_MAX + 1]; assert_success(chdir(test_data)); strcpy(lwin.curr_dir, test_data); strcpy(rwin.curr_dir, ".."); assert_success(cmds_dispatch("cd read rename", &lwin, CIT_COMMAND)); snprintf(path, sizeof(path), "%s/read", test_data); assert_true(paths_are_equal(lwin.curr_dir, path)); snprintf(path, sizeof(path), "%s/rename", test_data); assert_true(paths_are_equal(rwin.curr_dir, path)); } TEST(tr_extends_second_field) { char path[PATH_MAX + 1]; assert_success(chdir(sandbox)); strcpy(lwin.curr_dir, sandbox); snprintf(path, sizeof(path), "%s/a b", sandbox); create_file(path); lwin.list_rows = 1; lwin.list_pos = 0; lwin.dir_entry = dynarray_cextend(NULL, lwin.list_rows*sizeof(*lwin.dir_entry)); lwin.dir_entry[0].name = strdup("a b"); lwin.dir_entry[0].origin = &lwin.curr_dir[0]; (void)cmds_dispatch("tr/ ?<>\\\\:*|\"/_", &lwin, CIT_COMMAND); snprintf(path, sizeof(path), "%s/a_b", sandbox); assert_success(remove(path)); } TEST(substitute_works) { char path[PATH_MAX + 1]; assert_success(chdir(sandbox)); strcpy(lwin.curr_dir, sandbox); snprintf(path, sizeof(path), "%s/a b b", sandbox); create_file(path); snprintf(path, sizeof(path), "%s/B c", sandbox); create_file(path); lwin.list_rows = 2; lwin.list_pos = 0; lwin.dir_entry = dynarray_cextend(NULL, lwin.list_rows*sizeof(*lwin.dir_entry)); lwin.dir_entry[0].name = strdup("a b b"); lwin.dir_entry[0].origin = &lwin.curr_dir[0]; lwin.dir_entry[1].name = strdup("B c"); lwin.dir_entry[1].origin = &lwin.curr_dir[0]; (void)cmds_dispatch("%substitute/b/c/Iig", &lwin, CIT_COMMAND); snprintf(path, sizeof(path), "%s/a c c", sandbox); assert_success(remove(path)); snprintf(path, sizeof(path), "%s/c c", sandbox); assert_success(remove(path)); } TEST(chmod_works, IF(not_windows)) { char path[PATH_MAX + 1]; assert_success(chdir(sandbox)); strcpy(lwin.curr_dir, sandbox); snprintf(path, sizeof(path), "%s/file1", sandbox); create_file(path); snprintf(path, sizeof(path), "%s/file2", sandbox); create_file(path); lwin.list_rows = 2; lwin.list_pos = 0; lwin.dir_entry = dynarray_cextend(NULL, lwin.list_rows*sizeof(*lwin.dir_entry)); lwin.dir_entry[0].name = strdup("file1"); lwin.dir_entry[0].origin = &lwin.curr_dir[0]; lwin.dir_entry[1].name = strdup("file2"); lwin.dir_entry[1].origin = &lwin.curr_dir[0]; (void)cmds_dispatch("1,2chmod +x", &lwin, CIT_COMMAND); populate_dir_list(&lwin, 1); assert_int_equal(FT_EXEC, lwin.dir_entry[0].type); assert_int_equal(FT_EXEC, lwin.dir_entry[1].type); snprintf(path, sizeof(path), "%s/file1", sandbox); assert_success(remove(path)); snprintf(path, sizeof(path), "%s/file2", sandbox); assert_success(remove(path)); } TEST(putting_files_works) { char path[PATH_MAX + 1]; regs_init(); assert_success(os_mkdir(SANDBOX_PATH "/empty-dir", 0700)); assert_success(flist_load_tree(&lwin, sandbox, INT_MAX)); make_abs_path(path, sizeof(path), TEST_DATA_PATH, "read/binary-data", cwd); assert_success(regs_append(DEFAULT_REG_NAME, path)); lwin.list_pos = 1; assert_true(cmds_dispatch("put", &lwin, CIT_COMMAND) != 0); restore_cwd(saved_cwd); saved_cwd = save_cwd(); assert_success(unlink(SANDBOX_PATH "/empty-dir/binary-data")); assert_success(rmdir(SANDBOX_PATH "/empty-dir")); regs_reset(); } TEST(yank_works_with_ranges) { char path[PATH_MAX + 1]; const reg_t *reg; regs_init(); flist_custom_start(&lwin, "test"); snprintf(path, sizeof(path), "%s/%s", test_data, "existing-files/a"); flist_custom_add(&lwin, path); assert_true(flist_custom_finish(&lwin, CV_REGULAR, 0) == 0); reg = regs_find(DEFAULT_REG_NAME); assert_non_null(reg); assert_int_equal(0, reg->nfiles); (void)cmds_dispatch("%yank", &lwin, CIT_COMMAND); assert_int_equal(1, reg->nfiles); regs_reset(); } TEST(symlinks_in_paths_are_not_resolved, IF(not_windows)) { char canonic_path[PATH_MAX + 1]; char buf[PATH_MAX + 1]; assert_success(os_mkdir(SANDBOX_PATH "/dir1", 0700)); assert_success(os_mkdir(SANDBOX_PATH "/dir1/dir2", 0700)); char src[PATH_MAX + 1], dst[PATH_MAX + 1]; make_abs_path(src, sizeof(src), SANDBOX_PATH, "dir1/dir2", saved_cwd); make_abs_path(dst, sizeof(dst), SANDBOX_PATH, "dir-link", saved_cwd); assert_success(make_symlink(src, dst)); assert_success(chdir(SANDBOX_PATH "/dir-link")); make_abs_path(buf, sizeof(buf), SANDBOX_PATH, "dir-link", saved_cwd); to_canonic_path(buf, "/fake-root", lwin.curr_dir, sizeof(lwin.curr_dir)); to_canonic_path(sandbox, "/fake-root", canonic_path, sizeof(canonic_path)); /* :mkdir */ (void)cmds_dispatch("mkdir ../dir", &lwin, CIT_COMMAND); restore_cwd(saved_cwd); saved_cwd = save_cwd(); assert_success(rmdir(SANDBOX_PATH "/dir")); /* :clone file name. */ create_file(SANDBOX_PATH "/dir-link/file"); populate_dir_list(&lwin, 1); (void)cmds_dispatch("clone ../file-clone", &lwin, CIT_COMMAND); restore_cwd(saved_cwd); saved_cwd = save_cwd(); assert_success(remove(SANDBOX_PATH "/file-clone")); assert_success(remove(SANDBOX_PATH "/dir-link/file")); /* :colorscheme */ make_abs_path(cfg.colors_dir, sizeof(cfg.colors_dir), TEST_DATA_PATH, "scripts/", saved_cwd); snprintf(buf, sizeof(buf), "colorscheme set-env %s/../dir-link/..", sandbox); assert_success(cmds_dispatch(buf, &lwin, CIT_COMMAND)); cs_load_defaults(); /* :cd */ assert_success(cmds_dispatch("cd ../dir-link/..", &lwin, CIT_COMMAND)); assert_string_equal(canonic_path, lwin.curr_dir); restore_cwd(saved_cwd); saved_cwd = save_cwd(); assert_success(remove(SANDBOX_PATH "/dir-link")); assert_success(rmdir(SANDBOX_PATH "/dir1/dir2")); assert_success(rmdir(SANDBOX_PATH "/dir1")); } TEST(grep_command, IF(not_windows)) { opt_handlers_setup(); replace_string(&cfg.shell, "/bin/sh"); update_string(&cfg.shell_cmd_flag, "-c"); assert_success(chdir(TEST_DATA_PATH "/scripts")); assert_non_null(get_cwd(lwin.curr_dir, sizeof(lwin.curr_dir))); assert_success(cmds_dispatch("set grepprg='grep -n -H -r %i %a %s %u'", &lwin, CIT_COMMAND)); /* Nothing to repeat. */ assert_failure(cmds_dispatch("grep", &lwin, CIT_COMMAND)); assert_success(cmds_dispatch("grep command", &lwin, CIT_COMMAND)); assert_int_equal(2, lwin.list_rows); assert_string_equal("Grep command", lwin.custom.title); /* Repeat last grep, but add inversion. */ assert_success(cmds_dispatch("grep!", &lwin, CIT_COMMAND)); assert_int_equal(5, lwin.list_rows); assert_string_equal("Grep command", lwin.custom.title); opt_handlers_teardown(); } TEST(touch) { to_canonic_path(SANDBOX_PATH, cwd, lwin.curr_dir, sizeof(lwin.curr_dir)); (void)cmds_dispatch("touch file", &lwin, CIT_COMMAND); assert_success(remove(SANDBOX_PATH "/file")); } TEST(compare) { opt_handlers_setup(); create_file(SANDBOX_PATH "/file"); to_canonic_path(SANDBOX_PATH, cwd, lwin.curr_dir, sizeof(lwin.curr_dir)); /* The file is empty so nothing to do when "skipempty" is specified. */ assert_success(cmds_dispatch("compare ofone skipempty", &lwin, CIT_COMMAND)); assert_false(flist_custom_active(&lwin)); /* Verify that later arguments override the former ones. */ (void)cmds_dispatch("compare byname bysize bycontents listall listdups " "listunique ofboth ofone groupids grouppaths", &lwin, CIT_COMMAND); assert_true(flist_custom_active(&lwin)); assert_int_equal(CV_REGULAR, lwin.custom.type); rn_leave(&lwin, /*levels=*/1); /* Can't toggle without !. */ (void)cmds_dispatch("compare byname", &lwin, CIT_COMMAND); assert_int_equal(CF_GROUP_PATHS | CF_SHOW, lwin.custom.diff_cmp_flags); (void)cmds_dispatch("compare showdifferent", &lwin, CIT_COMMAND); assert_int_equal(CF_GROUP_PATHS | CF_SHOW, lwin.custom.diff_cmp_flags); rn_leave(&lwin, /*levels=*/1); /* No toggling. */ (void)cmds_dispatch("compare! showdifferent", &lwin, CIT_COMMAND); assert_string_equal("Toggling requires active compare view", ui_sb_last()); /* Verify that two-pane compare gets correct arguments. */ make_abs_path(rwin.curr_dir, sizeof(rwin.curr_dir), TEST_DATA_PATH, "rename", cwd); (void)cmds_dispatch("compare byname withrcase withicase", &lwin, CIT_COMMAND); assert_true(flist_custom_active(&lwin)); assert_true(flist_custom_active(&rwin)); assert_int_equal(CT_NAME, lwin.custom.diff_cmp_type); assert_int_equal(LT_ALL, lwin.custom.diff_list_type); assert_int_equal(CF_GROUP_PATHS | CF_IGNORE_CASE | CF_SHOW, lwin.custom.diff_cmp_flags); /* Toggling. */ (void)cmds_dispatch("compare! showidentical showdifferent", &lwin, CIT_COMMAND); assert_true(flist_custom_active(&lwin)); assert_true(flist_custom_active(&rwin)); assert_int_equal(CT_NAME, lwin.custom.diff_cmp_type); assert_int_equal(LT_ALL, lwin.custom.diff_list_type); assert_int_equal(CF_GROUP_PATHS | CF_IGNORE_CASE | CF_SHOW_UNIQUE_LEFT | CF_SHOW_UNIQUE_RIGHT, lwin.custom.diff_cmp_flags); /* Bad toggling. */ (void)cmds_dispatch("compare! byname", &lwin, CIT_COMMAND); assert_int_equal(CF_GROUP_PATHS | CF_IGNORE_CASE | CF_SHOW_UNIQUE_LEFT | CF_SHOW_UNIQUE_RIGHT, lwin.custom.diff_cmp_flags); assert_string_equal("Unexpected property for toggling: byname", ui_sb_last()); assert_success(chdir(cwd)); assert_success(remove(SANDBOX_PATH "/file")); opt_handlers_teardown(); } TEST(screen) { assert_false(cfg.use_term_multiplexer); /* :screen toggles the option. */ assert_success(cmds_dispatch("screen", &lwin, CIT_COMMAND)); assert_true(cfg.use_term_multiplexer); assert_success(cmds_dispatch("screen", &lwin, CIT_COMMAND)); assert_false(cfg.use_term_multiplexer); /* :screen! sets it to on. */ assert_success(cmds_dispatch("screen!", &lwin, CIT_COMMAND)); assert_true(cfg.use_term_multiplexer); assert_success(cmds_dispatch("screen!", &lwin, CIT_COMMAND)); assert_true(cfg.use_term_multiplexer); cfg.use_term_multiplexer = 0; } TEST(hist_next_and_prev) { /* Emulate proper history initialization (must happen after view * initialization). */ cfg_resize_histories(10); cfg_resize_histories(0); cfg_resize_histories(10); flist_hist_setup(&lwin, sandbox, ".", 0, 1); flist_hist_setup(&lwin, test_data, ".", 0, 1); assert_success(cmds_dispatch("histprev", &lwin, CIT_COMMAND)); assert_true(paths_are_same(lwin.curr_dir, sandbox)); assert_success(cmds_dispatch("histnext", &lwin, CIT_COMMAND)); assert_true(paths_are_same(lwin.curr_dir, test_data)); cfg_resize_histories(0); } TEST(normal_command_does_not_reset_selection) { modes_init(); opt_handlers_setup(); lwin.list_rows = 2; lwin.list_pos = 0; lwin.dir_entry = dynarray_cextend(NULL, lwin.list_rows*sizeof(*lwin.dir_entry)); lwin.dir_entry[0].name = strdup("a"); lwin.dir_entry[0].origin = &lwin.curr_dir[0]; lwin.dir_entry[0].selected = 1; lwin.dir_entry[1].name = strdup("b"); lwin.dir_entry[1].origin = &lwin.curr_dir[0]; lwin.dir_entry[1].selected = 0; lwin.selected_files = 1; assert_success(cmds_dispatch(":normal! t", &lwin, CIT_COMMAND)); assert_int_equal(0, lwin.selected_files); assert_false(lwin.dir_entry[0].selected); assert_false(lwin.dir_entry[1].selected); assert_success(cmds_dispatch(":normal! vG\r", &lwin, CIT_COMMAND)); assert_int_equal(2, lwin.selected_files); assert_true(lwin.dir_entry[0].selected); assert_true(lwin.dir_entry[1].selected); assert_success(cmds_dispatch(":normal! t", &lwin, CIT_COMMAND)); assert_int_equal(1, lwin.selected_files); assert_true(lwin.dir_entry[0].selected); assert_false(lwin.dir_entry[1].selected); opt_handlers_teardown(); vle_keys_reset(); } TEST(keepsel_preserves_selection) { init_view_list(&lwin); lwin.dir_entry[0].selected = 1; lwin.selected_files = 1; assert_failure(cmds_dispatch("echo 'hi'", &lwin, CIT_COMMAND)); assert_int_equal(0, lwin.selected_files); assert_false(lwin.dir_entry[0].selected); lwin.dir_entry[0].selected = 1; lwin.selected_files = 1; assert_failure(cmds_dispatch("keepsel echo 'hi'", &lwin, CIT_COMMAND)); assert_int_equal(1, lwin.selected_files); assert_true(lwin.dir_entry[0].selected); } TEST(echo_reports_all_errors) { const char *expected; expected = "Expression is missing closing quote: \"hi\n" "Invalid expression: \"hi"; ui_sb_msg(""); assert_failure(cmds_dispatch("echo \"hi", &lwin, CIT_COMMAND)); assert_string_equal(expected, ui_sb_last()); expected = "Expression is missing closing parenthesis: (1\n" "Invalid expression: (1"; ui_sb_msg(""); assert_failure(cmds_dispatch("echo (1", &lwin, CIT_COMMAND)); assert_string_equal(expected, ui_sb_last()); char zeroes[8192] = "echo "; memset(zeroes + strlen(zeroes), '0', sizeof(zeroes) - (strlen(zeroes) + 1U)); zeroes[sizeof(zeroes) - 1U] = '\0'; ui_sb_msg(""); assert_failure(cmds_dispatch(zeroes, &lwin, CIT_COMMAND)); assert_true(strchr(ui_sb_last(), '\n') != NULL); } TEST(echo_without_arguments_prints_nothing) { ui_sb_msg(""); /* First, print some message to record it as the last one. */ assert_failure(cmds_dispatch("echo 'previous'", &lwin, CIT_COMMAND)); assert_string_equal("previous", ui_sb_last()); /* Now, no message. The last one could popup here. */ assert_failure(cmds_dispatch("echo", &lwin, CIT_COMMAND)); assert_string_equal("", ui_sb_last()); } TEST(zero_count_is_rejected) { const char *expected = "Count argument can't be zero"; ui_sb_msg(""); assert_failure(cmds_dispatch("delete a 0", &lwin, CIT_COMMAND)); assert_string_equal(expected, ui_sb_last()); ui_sb_msg(""); assert_failure(cmds_dispatch("yank a 0", &lwin, CIT_COMMAND)); assert_string_equal(expected, ui_sb_last()); } TEST(tree_command) { strcpy(lwin.curr_dir, sandbox); /* Invalid input. */ assert_failure(cmds_dispatch("tree nesting=0", &lwin, CIT_COMMAND)); assert_false(flist_custom_active(&lwin)); assert_string_equal("Invalid argument: nesting=0", ui_sb_last()); assert_failure(cmds_dispatch("tree depth=0", &lwin, CIT_COMMAND)); assert_false(flist_custom_active(&lwin)); assert_string_equal("Invalid depth: 0", ui_sb_last()); /* :tree enters tree mode. */ assert_success(cmds_dispatch("tree", &lwin, CIT_COMMAND)); assert_true(flist_custom_active(&lwin)); assert_true(cv_tree(lwin.custom.type)); /* Repeating :tree leaves view in tree mode. */ assert_success(cmds_dispatch("tree", &lwin, CIT_COMMAND)); assert_true(flist_custom_active(&lwin)); assert_true(cv_tree(lwin.custom.type)); /* :tree! can leave tree mode. */ assert_success(cmds_dispatch("tree!", &lwin, CIT_COMMAND)); assert_false(flist_custom_active(&lwin)); /* :tree! can enter tree mode. */ assert_success(cmds_dispatch("tree!", &lwin, CIT_COMMAND)); assert_true(flist_custom_active(&lwin)); assert_true(cv_tree(lwin.custom.type)); /* Limited nesting. */ char sub_path[PATH_MAX + 1]; snprintf(sub_path, sizeof(sub_path), "%s/sub", sandbox); create_dir(sub_path); char sub_sub_path[PATH_MAX + 1]; snprintf(sub_sub_path, sizeof(sub_sub_path), "%s/sub/sub", sandbox); create_dir(sub_sub_path); assert_success(cmds_dispatch("tree depth=1", &lwin, CIT_COMMAND)); assert_true(flist_custom_active(&lwin)); assert_true(cv_tree(lwin.custom.type)); assert_int_equal(1, lwin.list_rows); remove_dir(sub_sub_path); remove_dir(sub_path); } TEST(regular_command) { strcpy(lwin.curr_dir, sandbox); /* :tree enters tree mode. */ assert_success(cmds_dispatch("tree", &lwin, CIT_COMMAND)); assert_true(flist_custom_active(&lwin)); assert_true(cv_tree(lwin.custom.type)); /* :regular leaves tree mode. */ assert_success(cmds_dispatch("regular", &lwin, CIT_COMMAND)); assert_false(flist_custom_active(&lwin)); /* Repeated :regular does nothing. */ assert_success(cmds_dispatch("regular", &lwin, CIT_COMMAND)); assert_false(flist_custom_active(&lwin)); } TEST(plugin_command) { curr_stats.vlua = vlua_init(); curr_stats.plugs = plugs_create(curr_stats.vlua); ui_sb_msg(""); assert_failure(cmds_dispatch("plugin load all", &lwin, CIT_COMMAND)); assert_string_equal("Trailing characters", ui_sb_last()); assert_failure(cmds_dispatch("plugin wrong arg", &lwin, CIT_COMMAND)); assert_string_equal("Unknown subcommand: wrong", ui_sb_last()); assert_failure(cmds_dispatch("plugin args-count", &lwin, CIT_COMMAND)); assert_string_equal("Too few arguments", ui_sb_last()); assert_success(cmds_dispatch("plugin load", &lwin, CIT_COMMAND)); strlist_t empty_list = {}; char *plug_items[] = { "plug" }; strlist_t plug_list = { .items = plug_items, .nitems = 1 }; ui_sb_msg(""); assert_success(cmds_dispatch("plugin blacklist plug", &lwin, CIT_COMMAND)); assert_string_equal("", ui_sb_last()); strings_list_is(plug_list, plugs_get_blacklist(curr_stats.plugs)); strings_list_is(empty_list, plugs_get_whitelist(curr_stats.plugs)); ui_sb_msg(""); assert_success(cmds_dispatch("plugin whitelist plug", &lwin, CIT_COMMAND)); assert_success(cmds_dispatch("plugin whitelist plug", &lwin, CIT_COMMAND)); assert_string_equal("", ui_sb_last()); strings_list_is(plug_list, plugs_get_blacklist(curr_stats.plugs)); strings_list_is(plug_list, plugs_get_whitelist(curr_stats.plugs)); plugs_free(curr_stats.plugs); curr_stats.plugs = NULL; vlua_finish(curr_stats.vlua); curr_stats.vlua = NULL; } TEST(help_command) { curr_stats.exec_env_type = EET_EMULATOR; update_string(&cfg.vi_command, "#vifmtest#editor"); curr_stats.vlua = vlua_init(); GLUA_EQ(curr_stats.vlua, "", "function handler(info) ginfo = info; return { success = false } end"); GLUA_EQ(curr_stats.vlua, "", "vifm.addhandler{ name = 'editor', handler = handler }"); cfg.use_vim_help = 0; assert_success(cmds_dispatch("help", &lwin, CIT_COMMAND)); char help_file[PATH_MAX + 1]; build_path(help_file, sizeof(help_file), get_installed_data_dir(), VIFM_HELP); GLUA_EQ(curr_stats.vlua, "edit-one", "print(ginfo.action)"); GLUA_EQ(curr_stats.vlua, help_file, "print(ginfo.path)"); GLUA_EQ(curr_stats.vlua, "false", "print(ginfo.mustwait)"); GLUA_EQ(curr_stats.vlua, "nil", "print(ginfo.line)"); GLUA_EQ(curr_stats.vlua, "nil", "print(ginfo.column)"); cfg.use_vim_help = 1; assert_success(cmds_dispatch("help", &lwin, CIT_COMMAND)); GLUA_EQ(curr_stats.vlua, "open-help", "print(ginfo.action)"); GLUA_EQ(curr_stats.vlua, "vifm-app.txt", "print(ginfo.topic)"); GLUA_ENDS(curr_stats.vlua, "/vim-doc", "print(ginfo.vimdocdir)"); cfg.use_vim_help = 0; vlua_finish(curr_stats.vlua); curr_stats.vlua = NULL; } TEST(view_command) { opt_handlers_setup(); curr_stats.preview.on = 0; assert_success(cmds_dispatch("view", &lwin, CIT_COMMAND)); assert_true(curr_stats.preview.on); assert_success(cmds_dispatch("view", &lwin, CIT_COMMAND)); assert_false(curr_stats.preview.on); assert_success(cmds_dispatch("view!", &lwin, CIT_COMMAND)); assert_true(curr_stats.preview.on); assert_success(cmds_dispatch("view!", &lwin, CIT_COMMAND)); assert_true(curr_stats.preview.on); assert_success(cmds_dispatch("view", &lwin, CIT_COMMAND)); assert_false(curr_stats.preview.on); opt_handlers_teardown(); } TEST(invert_command) { opt_handlers_setup(); ui_sb_msg(""); assert_failure(cmds_dispatch("set sort? sortorder?", &lwin, CIT_COMMAND)); assert_string_equal(" sort=+name\n sortorder=ascending", ui_sb_last()); assert_success(cmds_dispatch("invert o", &lwin, CIT_COMMAND)); ui_sb_msg(""); assert_failure(cmds_dispatch("set sort? sortorder?", &lwin, CIT_COMMAND)); assert_string_equal(" sort=-name\n sortorder=descending", ui_sb_last()); opt_handlers_teardown(); } TEST(locate_command) { ui_sb_msg(""); /* Nothing to repeat. */ assert_failure(cmds_dispatch("locate", &lwin, CIT_COMMAND)); assert_string_equal("Nothing to repeat", ui_sb_last()); } TEST(registers_command) { regs_init(); curr_stats.load_stage = -1; regs_append(DEFAULT_REG_NAME, "def"); assert_success(cmds_dispatch1("registers", &lwin, CIT_COMMAND)); assert_int_equal(2, menu_get_current()->len); regs_append('a', "a"); regs_append('b', "b1"); regs_append('b', "b2"); assert_success(cmds_dispatch1("registers aababaa", &lwin, CIT_COMMAND)); assert_int_equal(5, menu_get_current()->len); curr_stats.load_stage = 0; regs_reset(); } TEST(open_command) { curr_stats.vlua = vlua_init(); GLUA_EQ(curr_stats.vlua, "", "function editor(i) info = i end"); GLUA_EQ(curr_stats.vlua, "", "vifm.addhandler{ name = 'editor', handler = editor }"); update_string(&cfg.vi_command, "#vifmtest#editor"); create_file(SANDBOX_PATH "/to-open"); create_file(SANDBOX_PATH "/to-open-2"); lwin.list_rows = 2; lwin.list_pos = 0; lwin.dir_entry = dynarray_cextend(NULL, lwin.list_rows*sizeof(*lwin.dir_entry)); lwin.dir_entry[0].name = strdup("to-open"); lwin.dir_entry[0].origin = &lwin.curr_dir[0]; lwin.dir_entry[1].name = strdup("to-open-2"); lwin.dir_entry[1].origin = &lwin.curr_dir[0]; strcpy(lwin.curr_dir, sandbox); assert_success(cmds_dispatch1("open \"comment", &lwin, CIT_COMMAND)); GLUA_EQ(curr_stats.vlua, "1", "print(#info.paths)"); GLUA_EQ(curr_stats.vlua, "to-open", "print(info.paths[1])"); assert_success(cmds_dispatch1("%open", &lwin, CIT_COMMAND)); GLUA_EQ(curr_stats.vlua, "2", "print(#info.paths)"); GLUA_EQ(curr_stats.vlua, "to-open", "print(info.paths[1])"); GLUA_EQ(curr_stats.vlua, "to-open-2", "print(info.paths[2])"); remove_file(SANDBOX_PATH "/to-open"); remove_file(SANDBOX_PATH "/to-open-2"); vlua_finish(curr_stats.vlua); curr_stats.vlua = NULL; } TEST(mark_command) { /* Bad mark name. */ ui_sb_msg(""); assert_failure(cmds_dispatch1("mark ab", &lwin, CIT_COMMAND)); assert_string_equal("Invalid mark name: ab", ui_sb_last()); assert_failure(cmds_dispatch1("mark &", &lwin, CIT_COMMAND)); assert_string_equal("Invalid mark name: &", ui_sb_last()); /* Relative paths are rejected. */ ui_sb_msg(""); assert_failure(cmds_dispatch1("mark x aaaaa", &lwin, CIT_COMMAND)); assert_string_equal("Expected full path to a directory", ui_sb_last()); /* Environment variables are expanded. */ assert_success(cmds_dispatch1("let $TEST = '/'", &lwin, CIT_COMMAND)); assert_success(cmds_dispatch1("mark x $TEST", &lwin, CIT_COMMAND)); const mark_t *mark = get_mark_by_name(&lwin, 'x'); assert_non_null(mark); assert_string_equal("/", mark->directory); /* Question mark prevents mark overwrite. */ ui_sb_msg(""); assert_failure(cmds_dispatch1("mark? x /tmp", &lwin, CIT_COMMAND)); assert_string_equal("Mark isn't empty: x", ui_sb_last()); /* Not an overwrite. */ assert_success(cmds_dispatch1("mark? y /tmp", &lwin, CIT_COMMAND)); } static void strings_list_is(const strlist_t expected, const strlist_t actual) { assert_int_equal(expected.nitems, actual.nitems); int i; for(i = 0; i < MIN(expected.nitems, actual.nitems); ++i) { assert_string_equal(expected.items[i], actual.items[i]); } } /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set cinoptions+=t0 : */