1 #include <stic.h>
2
3 #include <sys/time.h> /* timeval utimes() */
4 #include <unistd.h> /* rmdir() symlink() */
5
6 #include <stddef.h> /* NULL */
7 #include <stdlib.h> /* free() remove() */
8 #include <string.h> /* strdup() */
9
10 #include <test-utils.h>
11
12 #include "../../src/cfg/config.h"
13 #include "../../src/compat/fs_limits.h"
14 #include "../../src/compat/os.h"
15 #include "../../src/engine/functions.h"
16 #include "../../src/engine/parsing.h"
17 #include "../../src/engine/variables.h"
18 #include "../../src/utils/env.h"
19 #include "../../src/utils/fs.h"
20 #include "../../src/utils/str.h"
21 #include "../../src/args.h"
22 #include "../../src/builtin_functions.h"
23 #include "../../src/compare.h"
24 #include "../../src/filelist.h"
25 #include "../../src/status.h"
26 #include "../parsing/asserts.h"
27
SETUP()28 SETUP()
29 {
30 update_string(&cfg.shell, "sh");
31 update_string(&cfg.shell_cmd_flag, "-c");
32
33 init_builtin_functions();
34 init_parser(NULL);
35 init_variables();
36
37 view_setup(&lwin);
38
39 assert_non_null(get_cwd(lwin.curr_dir, sizeof(lwin.curr_dir)));
40 }
41
TEARDOWN()42 TEARDOWN()
43 {
44 clear_envvars();
45 function_reset_all();
46 update_string(&cfg.shell, NULL);
47 update_string(&cfg.shell_cmd_flag, NULL);
48
49 view_teardown(&lwin);
50 }
51
TEST(executable_true_for_executable)52 TEST(executable_true_for_executable)
53 {
54 const char *const exec_file = SANDBOX_PATH "/exec-for-completion" EXE_SUFFIX;
55
56 create_executable(exec_file);
57
58 ASSERT_INT_OK(
59 "executable('" SANDBOX_PATH "/exec-for-completion" EXE_SUFFIX "')", 1);
60
61 assert_success(remove(exec_file));
62 }
63
TEST(executable_false_for_regular_file)64 TEST(executable_false_for_regular_file)
65 {
66 ASSERT_INT_OK("executable('Makefile')", 0);
67 }
68
TEST(executable_false_for_dir)69 TEST(executable_false_for_dir)
70 {
71 ASSERT_INT_OK("executable('.')", 0);
72 }
73
TEST(expand_expands_environment_variables)74 TEST(expand_expands_environment_variables)
75 {
76 let_variables("$OPEN_ME = 'Found something interesting?'");
77 ASSERT_OK("expand('$OPEN_ME')", "Found something interesting?");
78 }
79
TEST(system_catches_stdout)80 TEST(system_catches_stdout)
81 {
82 ASSERT_OK("system('echo a')", "a");
83 }
84
TEST(system_catches_stderr)85 TEST(system_catches_stderr)
86 {
87 #ifndef _WIN32
88 ASSERT_OK("system('echo a 1>&2')", "a");
89 #else
90 /* "echo" implemented by cmd.exe is kinda disabled, and doesn't ignore
91 * spaces. */
92 ASSERT_OK("system('echo a 1>&2')", "a ");
93 #endif
94 }
95
TEST(system_catches_stdout_and_err)96 TEST(system_catches_stdout_and_err)
97 {
98 #ifndef _WIN32
99 ASSERT_OK("system('echo a && echo b 1>&2')", "a\nb");
100 #else
101 /* "echo" implemented by cmd.exe is kinda disabled, and doesn't ignore
102 * spaces. */
103 ASSERT_OK("system('echo a && echo b 1>&2')", "a \nb ");
104 #endif
105 }
106
TEST(term_catches_stdout)107 TEST(term_catches_stdout)
108 {
109 ASSERT_OK("term('echo a')", "a");
110 }
111
TEST(layoutis_is_correct_for_single_pane)112 TEST(layoutis_is_correct_for_single_pane)
113 {
114 curr_stats.number_of_windows = 1;
115 curr_stats.split = VSPLIT;
116 curr_stats.split = HSPLIT;
117 ASSERT_OK("layoutis('only')", "1");
118 ASSERT_OK("layoutis('split')", "0");
119 ASSERT_OK("layoutis('hsplit')", "0");
120 ASSERT_OK("layoutis('vsplit')", "0");
121 }
122
TEST(layoutis_is_correct_for_hsplit)123 TEST(layoutis_is_correct_for_hsplit)
124 {
125 curr_stats.number_of_windows = 2;
126 curr_stats.split = HSPLIT;
127 ASSERT_OK("layoutis('only')", "0");
128 ASSERT_OK("layoutis('split')", "1");
129 ASSERT_OK("layoutis('hsplit')", "1");
130 ASSERT_OK("layoutis('vsplit')", "0");
131 }
132
TEST(layoutis_is_correct_for_vsplit)133 TEST(layoutis_is_correct_for_vsplit)
134 {
135 curr_stats.number_of_windows = 2;
136 curr_stats.split = VSPLIT;
137 ASSERT_OK("layoutis('only')", "0");
138 ASSERT_OK("layoutis('split')", "1");
139 ASSERT_OK("layoutis('hsplit')", "0");
140 ASSERT_OK("layoutis('vsplit')", "1");
141 }
142
TEST(paneisat_is_correct_for_single_pane)143 TEST(paneisat_is_correct_for_single_pane)
144 {
145 curr_stats.number_of_windows = 1;
146 curr_stats.split = VSPLIT;
147 curr_stats.split = HSPLIT;
148 ASSERT_OK("paneisat('top')", "1");
149 ASSERT_OK("paneisat('bottom')", "1");
150 ASSERT_OK("paneisat('left')", "1");
151 ASSERT_OK("paneisat('right')", "1");
152 }
153
TEST(paneisat_is_correct_for_hsplit)154 TEST(paneisat_is_correct_for_hsplit)
155 {
156 curr_stats.number_of_windows = 2;
157 curr_stats.split = HSPLIT;
158
159 curr_view = &lwin;
160 ASSERT_OK("paneisat('top')", "1");
161 ASSERT_OK("paneisat('bottom')", "0");
162 ASSERT_OK("paneisat('left')", "1");
163 ASSERT_OK("paneisat('right')", "1");
164
165 curr_view = &rwin;
166 ASSERT_OK("paneisat('top')", "0");
167 ASSERT_OK("paneisat('bottom')", "1");
168 ASSERT_OK("paneisat('left')", "1");
169 ASSERT_OK("paneisat('right')", "1");
170 }
171
TEST(paneisat_is_correct_for_vsplit)172 TEST(paneisat_is_correct_for_vsplit)
173 {
174 curr_stats.number_of_windows = 2;
175 curr_stats.split = VSPLIT;
176
177 curr_view = &lwin;
178 ASSERT_OK("paneisat('top')", "1");
179 ASSERT_OK("paneisat('bottom')", "1");
180 ASSERT_OK("paneisat('left')", "1");
181 ASSERT_OK("paneisat('right')", "0");
182
183 curr_view = &rwin;
184 ASSERT_OK("paneisat('top')", "1");
185 ASSERT_OK("paneisat('bottom')", "1");
186 ASSERT_OK("paneisat('left')", "0");
187 ASSERT_OK("paneisat('right')", "1");
188 }
189
TEST(getpanetype_for_regular_view)190 TEST(getpanetype_for_regular_view)
191 {
192 curr_view = &lwin;
193 ASSERT_OK("getpanetype()", "regular");
194 }
195
TEST(getpanetype_for_custom_view)196 TEST(getpanetype_for_custom_view)
197 {
198 flist_custom_start(&lwin, "test");
199 flist_custom_add(&lwin, TEST_DATA_PATH "/existing-files/a");
200 assert_true(flist_custom_finish(&lwin, CV_REGULAR, 0) == 0);
201
202 curr_view = &lwin;
203 ASSERT_OK("getpanetype()", "custom");
204 }
205
TEST(getpanetype_for_very_custom_view)206 TEST(getpanetype_for_very_custom_view)
207 {
208 opt_handlers_setup();
209
210 flist_custom_start(&lwin, "test");
211 flist_custom_add(&lwin, TEST_DATA_PATH "/existing-files/a");
212 assert_true(flist_custom_finish(&lwin, CV_VERY, 0) == 0);
213
214 curr_view = &lwin;
215 ASSERT_OK("getpanetype()", "very-custom");
216
217 opt_handlers_teardown();
218 }
219
TEST(getpanetype_for_tree_view)220 TEST(getpanetype_for_tree_view)
221 {
222 flist_load_tree(&lwin, TEST_DATA_PATH);
223
224 curr_view = &lwin;
225 ASSERT_OK("getpanetype()", "tree");
226 }
227
TEST(getpanetype_for_compare_view)228 TEST(getpanetype_for_compare_view)
229 {
230 strcpy(lwin.curr_dir, TEST_DATA_PATH "/rename");
231
232 curr_view = &lwin;
233 other_view = &rwin;
234
235 opt_handlers_setup();
236 compare_one_pane(&lwin, CT_CONTENTS, LT_DUPS, 0);
237 opt_handlers_teardown();
238
239 ASSERT_OK("getpanetype()", "compare");
240 }
241
TEST(chooseopt_options_are_not_set)242 TEST(chooseopt_options_are_not_set)
243 {
244 args_t args = { };
245 char *argv[] = { "vifm", NULL };
246
247 assert_success(stats_init(&cfg));
248
249 args_parse(&args, ARRAY_LEN(argv) - 1U, argv, "/");
250 args_process(&args, 0);
251 args_process(&args, 1);
252
253 ASSERT_OK("chooseopt('files')", "");
254 ASSERT_OK("chooseopt('dir')", "");
255 ASSERT_OK("chooseopt('cmd')", "");
256 ASSERT_OK("chooseopt('delimiter')", "\n");
257
258 assert_success(stats_reset(&cfg));
259
260 args_free(&args);
261 }
262
TEST(chooseopt_options_are_set)263 TEST(chooseopt_options_are_set)
264 {
265 args_t args = { };
266 char *argv[] = { "vifm",
267 "--choose-files", "files-file",
268 "--choose-dir", "dir-file",
269 "--on-choose", "cmd",
270 "--delimiter", "delim",
271 NULL };
272
273 assert_success(stats_init(&cfg));
274
275 args_parse(&args, ARRAY_LEN(argv) - 1U, argv, "/");
276 args_process(&args, 0);
277 args_process(&args, 1);
278
279 ASSERT_OK("chooseopt('files')", "/files-file");
280 ASSERT_OK("chooseopt('dir')", "/dir-file");
281 ASSERT_OK("chooseopt('cmd')", "cmd");
282 ASSERT_OK("chooseopt('delimiter')", "delim");
283
284 assert_success(stats_reset(&cfg));
285
286 args_free(&args);
287 }
288
TEST(tabpagenr)289 TEST(tabpagenr)
290 {
291 ASSERT_OK("tabpagenr()", "1");
292 ASSERT_OK("tabpagenr('$')", "1");
293
294 ASSERT_FAIL("tabpagenr(1)", PE_INVALID_EXPRESSION);
295 ASSERT_FAIL("tabpagenr('a')", PE_INVALID_EXPRESSION);
296 }
297
TEST(fnameescape)298 TEST(fnameescape)
299 {
300 ASSERT_FAIL("fnameescape()", PE_INVALID_EXPRESSION);
301
302 ASSERT_OK("fnameescape(' ')", "\\ ");
303 ASSERT_OK("fnameescape('%')", "%%");
304 ASSERT_OK("fnameescape(\"'\")", "\\'");
305 ASSERT_OK("fnameescape('\"')", "\\\"");
306 }
307
TEST(filetype)308 TEST(filetype)
309 {
310 opt_handlers_setup();
311
312 /* symlink() is not available on Windows, but the rest of the code is fine. */
313 #ifndef _WIN32
314 char cwd[PATH_MAX + 1];
315 assert_non_null(get_cwd(cwd, sizeof(cwd)));
316 char test_data[PATH_MAX + 1];
317 make_abs_path(test_data, sizeof(test_data), TEST_DATA_PATH, "", cwd);
318
319 char path[PATH_MAX + 1];
320 snprintf(path, sizeof(path), "%s/existing-files", test_data);
321 assert_success(symlink(path, SANDBOX_PATH "/dir-link"));
322 snprintf(path, sizeof(path), "%s/existing-files/b", test_data);
323 assert_success(symlink(path, SANDBOX_PATH "/file-link"));
324 snprintf(path, sizeof(path), "%s/no-such-file", test_data);
325 assert_success(symlink(path, SANDBOX_PATH "/broken-link"));
326 #endif
327
328 flist_custom_start(&lwin, "test");
329 flist_custom_add(&lwin, TEST_DATA_PATH "/existing-files/a");
330 flist_custom_add(&lwin, TEST_DATA_PATH "/compare");
331 #ifndef _WIN32
332 flist_custom_add(&lwin, SANDBOX_PATH "/dir-link");
333 flist_custom_add(&lwin, SANDBOX_PATH "/file-link");
334 flist_custom_add(&lwin, SANDBOX_PATH "/broken-link");
335 #endif
336 assert_true(flist_custom_finish(&lwin, CV_VERY, 0) == 0);
337
338 curr_view = &lwin;
339
340 ASSERT_OK("filetype('')", "");
341 lwin.list_pos = 0;
342 ASSERT_OK("filetype('.')", "reg");
343 ASSERT_OK("filetype(1)", "reg");
344 ASSERT_OK("filetype(2)", "dir");
345 #ifndef _WIN32
346 ASSERT_OK("filetype('3')", "link");
347 ASSERT_OK("filetype('4')", "link");
348 ASSERT_OK("filetype('3', 1)", "dir");
349 ASSERT_OK("filetype('4', 1)", "reg");
350 ASSERT_OK("filetype(5, 1)", "broken");
351 #endif
352
353 opt_handlers_teardown();
354
355 #ifndef _WIN32
356 assert_success(remove(SANDBOX_PATH "/dir-link"));
357 assert_success(remove(SANDBOX_PATH "/file-link"));
358 assert_success(remove(SANDBOX_PATH "/broken-link"));
359 #endif
360 }
361
TEST(has)362 TEST(has)
363 {
364 #ifndef _WIN32
365 ASSERT_OK("has('unix')", "1");
366 ASSERT_OK("has('win')", "0");
367 #else
368 ASSERT_OK("has('unix')", "0");
369 ASSERT_OK("has('win')", "1");
370 #endif
371
372 ASSERT_OK("has('anythingelse')", "0");
373 ASSERT_OK("has('nix')", "0");
374 ASSERT_OK("has('windows')", "0");
375 }
376
TEST(extcached)377 TEST(extcached)
378 {
379 /* Testing with FMT_CHANGED is problematic, because change time is not
380 * programmatically accessible for writing. */
381 set_extcached_monitor_type(FMT_MODIFIED);
382
383 create_file("file");
384 assert_success(os_mkdir("dir", 0700));
385
386 /* For directories. */
387 ASSERT_OK("extcached('cache1', 'dir', 'echo 1')", "1");
388 /* Unchanged. */
389 ASSERT_OK("extcached('cache1', 'dir', 'echo 2')", "1");
390 #ifndef _WIN32
391 /* Changed. */
392 struct timeval tvs[2] = {};
393 assert_success(utimes("dir", tvs));
394 ASSERT_OK("extcached('cache1', 'dir', 'echo 3')", "3");
395 /* Unchanged again. */
396 ASSERT_OK("extcached('cache1', 'dir', 'echo 4')", "3");
397 #endif
398
399 /* For files. */
400 ASSERT_OK("extcached('cache1', 'file', 'echo 5')", "5");
401 /* Unchanged. */
402 ASSERT_OK("extcached('cache1', 'file', 'echo 6')", "5");
403 #ifndef _WIN32
404 /* Changed. */
405 assert_success(utimes("file", tvs));
406 ASSERT_OK("extcached('cache1', 'file', 'echo 7')", "7");
407 /* Unchanged again. */
408 ASSERT_OK("extcached('cache1', 'file', 'echo 8')", "7");
409 #endif
410
411 /* Caches don't mix. */
412 ASSERT_OK("extcached('cache2', 'dir', 'echo a')", "a");
413 ASSERT_OK("extcached('cache3', 'dir', 'echo b')", "b");
414
415 #ifndef _WIN32
416 /* Change resets all caches. */
417 tvs[0].tv_sec = 1;
418 tvs[1].tv_sec = 1;
419 assert_success(utimes("dir", tvs));
420 ASSERT_OK("extcached('cache1', 'dir', 'echo 00')", "00");
421 ASSERT_OK("extcached('cache2', 'dir', 'echo aa')", "aa");
422 ASSERT_OK("extcached('cache3', 'dir', 'echo bb')", "bb");
423 #endif
424
425 assert_success(remove("file"));
426 assert_success(rmdir("dir"));
427
428 set_extcached_monitor_type(FMT_CHANGED);
429 }
430
431 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
432 /* vim: set cinoptions+=t0 filetype=c : */
433