test_cd.vim (11541B)
1 " Test for :cd and chdir() 2 3 source shared.vim 4 source check.vim 5 6 func Test_cd_large_path() 7 " This used to crash with a heap write overflow. 8 call assert_fails('cd ' . repeat('x', 5000), 'E344:') 9 endfunc 10 11 func Test_cd_up_and_down() 12 let path = getcwd() 13 cd .. 14 call assert_notequal(path, getcwd()) 15 exe 'cd ' .. fnameescape(path) 16 call assert_equal(path, getcwd()) 17 endfunc 18 19 func Test_cd_no_arg() 20 if has('unix') 21 " Test that cd without argument goes to $HOME directory on Unix systems. 22 let path = getcwd() 23 cd 24 call assert_equal($HOME, getcwd()) 25 call assert_notequal(path, getcwd()) 26 exe 'cd ' .. fnameescape(path) 27 call assert_equal(path, getcwd()) 28 else 29 " Test that cd without argument echoes cwd on non-Unix systems. 30 call assert_match(getcwd(), execute('cd')) 31 endif 32 endfunc 33 34 func Test_cd_minus() 35 " Test the :cd - goes back to the previous directory. 36 let path = getcwd() 37 cd .. 38 let path_dotdot = getcwd() 39 call assert_notequal(path, path_dotdot) 40 cd - 41 call assert_equal(path, getcwd()) 42 cd - 43 call assert_equal(path_dotdot, getcwd()) 44 cd - 45 call assert_equal(path, getcwd()) 46 47 " Test for :cd - after a failed :cd 48 call assert_fails('cd /nonexistent', 'E344:') 49 call assert_equal(path, getcwd()) 50 cd - 51 call assert_equal(path_dotdot, getcwd()) 52 cd - 53 54 " Test for :cd - without a previous directory 55 let lines =<< trim [SCRIPT] 56 call assert_fails('cd -', 'E186:') 57 call assert_fails('call chdir("-")', 'E186:') 58 call writefile(v:errors, 'Xresult') 59 qall! 60 [SCRIPT] 61 call writefile(lines, 'Xscript', 'D') 62 if RunVim([], [], '--clean -S Xscript') 63 call assert_equal([], readfile('Xresult')) 64 endif 65 call delete('Xresult') 66 endfunc 67 68 " Test for chdir() 69 func Test_chdir_func() 70 let topdir = getcwd() 71 call mkdir('Xchdir/y/z', 'pR') 72 73 " Create a few tabpages and windows with different directories 74 new 75 cd Xchdir 76 tabnew 77 tcd y 78 below new 79 below new 80 lcd z 81 82 tabfirst 83 call assert_match('^\[global\] .*/Xchdir$', trim(execute('verbose pwd'))) 84 call chdir('..') 85 call assert_equal('y', fnamemodify(getcwd(1, 2), ':t')) 86 call assert_equal('z', fnamemodify(3->getcwd(2), ':t')) 87 tabnext | wincmd t 88 call assert_match('^\[tabpage\] .*/y$', trim(execute('verbose pwd'))) 89 eval '..'->chdir() 90 call assert_equal('Xchdir', fnamemodify(getcwd(1, 2), ':t')) 91 call assert_equal('Xchdir', fnamemodify(getcwd(2, 2), ':t')) 92 call assert_equal('z', fnamemodify(getcwd(3, 2), ':t')) 93 call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t')) 94 3wincmd w 95 call assert_match('^\[window\] .*/z$', trim(execute('verbose pwd'))) 96 call chdir('..') 97 call assert_equal('Xchdir', fnamemodify(getcwd(1, 2), ':t')) 98 call assert_equal('Xchdir', fnamemodify(getcwd(2, 2), ':t')) 99 call assert_equal('y', fnamemodify(getcwd(3, 2), ':t')) 100 call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t')) 101 102 " Forcing scope 103 call chdir('.', 'global') 104 call assert_match('^\[global\]', trim(execute('verbose pwd'))) 105 call chdir('.', 'tabpage') 106 call assert_match('^\[tabpage\]', trim(execute('verbose pwd'))) 107 call chdir('.', 'window') 108 call assert_match('^\[window\]', trim(execute('verbose pwd'))) 109 110 " Error case 111 call assert_fails("call chdir('dir-abcd')", 'E344:') 112 silent! let d = chdir("dir_abcd") 113 call assert_equal("", d) 114 call assert_fails("call chdir('.', v:_null_string)", 'E475:') 115 call assert_fails("call chdir('.', [])", 'E730:') 116 " Should not crash 117 call chdir(d) 118 call assert_equal('', chdir([])) 119 120 only | tabonly 121 call chdir(topdir) 122 endfunc 123 124 " Test for changing to the previous directory '-' 125 func Test_prev_dir() 126 let topdir = getcwd() 127 call mkdir('Xprevdir/a/b/c', 'pR') 128 129 " Create a few tabpages and windows with different directories 130 new | only 131 tabnew | new 132 tabnew 133 tabfirst 134 cd Xprevdir 135 tabnext | wincmd t 136 tcd a 137 wincmd w 138 lcd b 139 tabnext 140 tcd a/b/c 141 142 " Change to the previous directory twice in all the windows. 143 tabfirst 144 cd - | cd - 145 tabnext | wincmd t 146 tcd - | tcd - 147 wincmd w 148 lcd - | lcd - 149 tabnext 150 tcd - | tcd - 151 152 " Check the directory of all the windows 153 tabfirst 154 call assert_equal('Xprevdir', fnamemodify(getcwd(), ':t')) 155 tabnext | wincmd t 156 call assert_equal('a', fnamemodify(getcwd(), ':t')) 157 wincmd w 158 call assert_equal('b', fnamemodify(getcwd(), ':t')) 159 tabnext 160 call assert_equal('c', fnamemodify(getcwd(), ':t')) 161 162 " Change to the previous directory using chdir() 163 tabfirst 164 call chdir("-") | call chdir("-") 165 tabnext | wincmd t 166 call chdir("-") | call chdir("-") 167 wincmd w 168 call chdir("-") | call chdir("-") 169 tabnext 170 call chdir("-") | call chdir("-") 171 172 " Check the directory of all the windows 173 tabfirst 174 call assert_equal('Xprevdir', fnamemodify(getcwd(), ':t')) 175 tabnext | wincmd t 176 call assert_equal('a', fnamemodify(getcwd(), ':t')) 177 wincmd w 178 call assert_equal('b', fnamemodify(getcwd(), ':t')) 179 tabnext 180 call assert_equal('c', fnamemodify(getcwd(), ':t')) 181 182 only | tabonly 183 call chdir(topdir) 184 endfunc 185 186 func Test_lcd_split() 187 let curdir = getcwd() 188 lcd .. 189 split 190 lcd - 191 call assert_equal(curdir, getcwd()) 192 quit! 193 endfunc 194 195 " Test that a temporary override of 'autochdir' via :lcd isn't clobbered by win_execute() in a split window. 196 func Test_lcd_win_execute() 197 CheckFunction test_autochdir 198 CheckOption autochdir 199 200 let startdir = getcwd() 201 call mkdir('Xsubdir', 'R') 202 call test_autochdir() 203 set autochdir 204 edit Xsubdir/file 205 call assert_match('testdir.Xsubdir.file$', expand('%:p')) 206 split 207 lcd .. 208 call assert_match('testdir.Xsubdir.file$', expand('%:p')) 209 call win_execute(win_getid(2), "") 210 call assert_match('testdir.Xsubdir.file$', expand('%:p')) 211 212 set noautochdir 213 bwipe! 214 call chdir(startdir) 215 endfunc 216 217 func Test_cd_from_non_existing_dir() 218 CheckNotMSWindows 219 220 let saveddir = getcwd() 221 call mkdir('Xdeleted_dir') 222 cd Xdeleted_dir 223 call delete(saveddir .. '/Xdeleted_dir', 'd') 224 225 " Expect E187 as the current directory was deleted. 226 call assert_fails('pwd', 'E187:') 227 call assert_equal('', getcwd()) 228 cd - 229 call assert_equal(saveddir, getcwd()) 230 endfunc 231 232 func Test_cd_completion() 233 call mkdir('XComplDir1', 'D') 234 call mkdir('XComplDir2', 'D') 235 call mkdir('sub/XComplDir3', 'pD') 236 call writefile([], 'XComplFile', 'D') 237 238 for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir'] 239 call feedkeys(':' .. cmd .. " XCompl\<C-A>\<C-B>\"\<CR>", 'tx') 240 call assert_equal('"' .. cmd .. ' XComplDir1/ XComplDir2/', @:) 241 endfor 242 243 set cdpath+=sub 244 for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir'] 245 call feedkeys(':' .. cmd .. " XCompl\<C-A>\<C-B>\"\<CR>", 'tx') 246 call assert_equal('"' .. cmd .. ' XComplDir1/ XComplDir2/ XComplDir3/', @:) 247 endfor 248 set cdpath& 249 250 if has('win32') 251 " Test Windows absolute path completion 252 let saved_cwd = getcwd() 253 254 " Retrieve a suitable dir in the current drive 255 for d in readdir('/', 'isdirectory("/" .. v:val) && len(v:val) > 2') 256 " Paths containing '$' such as "$RECYCLE.BIN" are skipped because 257 " they are considered environment variables and completion does not 258 " work. 259 if d =~ '\V$' 260 continue 261 endif 262 " Skip directories that we don't have permission to "cd" into by 263 " actually "cd"ing into them and making sure they don't fail. 264 " Directory "System Volume Information" is an example of this. 265 try 266 call chdir('/' .. d) 267 let dir = d 268 " Yay! We found a suitable dir! 269 break 270 catch /:E472:/ 271 " Just skip directories where "cd" fails 272 continue 273 finally 274 call chdir(saved_cwd) 275 endtry 276 endfor 277 if !exists('dir') 278 throw 'Skipped: no testable directories found in the current drive root' 279 endif 280 281 " Get partial path 282 let partial = dir[0:-2] 283 " Get the current drive letter and full path of the target dir 284 call chdir('/' .. dir) 285 let full = getcwd() 286 let drive = full[0] 287 call chdir(saved_cwd) 288 289 " Spaces are escaped in command line completion. Next, in assert_match(), 290 " the backslash added by the first escape also needs to be escaped 291 " separately, so the escape is doubled. 292 let want_full = escape(escape(full, ' '), '\') 293 let want_dir = escape(escape(dir, ' '), '\') 294 295 for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir'] 296 for sep in [ '/', '\'] 297 298 " Explicit drive letter 299 call feedkeys(':' .. cmd .. ' ' .. drive .. ':' .. sep .. 300 \ partial .. "\<C-A>\<C-B>\"\<CR>", 'tx') 301 call assert_match(want_full, @:) 302 303 " Implicit drive letter 304 call feedkeys(':' .. cmd .. ' ' .. sep .. partial .. "\<C-A>\<C-B>\"\<CR>", 'tx') 305 call assert_match('/' .. want_dir .. '/', @:) 306 307 " UNC path 308 call feedkeys(':' .. cmd .. ' ' .. sep .. sep .. $COMPUTERNAME .. sep .. 309 \ drive .. '$' .. sep .. partial .."\<C-A>\<C-B>\"\<CR>", 'tx') 310 call assert_match('//' .. $COMPUTERNAME .. '/' .. drive .. '$/' .. want_dir .. '/' , @:) 311 312 endfor 313 endfor 314 endif 315 endfunc 316 317 func Test_cd_unknown_dir() 318 call mkdir('Xa', 'R') 319 cd Xa 320 call writefile(['text'], 'Xb.txt') 321 edit Xa/Xb.txt 322 let first_buf = bufnr() 323 cd .. 324 edit 325 call assert_equal(first_buf, bufnr()) 326 edit Xa/Xb.txt 327 call assert_notequal(first_buf, bufnr()) 328 329 bwipe! 330 exe "bwipe! " .. first_buf 331 endfunc 332 333 func Test_getcwd_actual_dir() 334 CheckFunction test_autochdir 335 CheckOption autochdir 336 337 let startdir = getcwd() 338 call mkdir('Xactual', 'R') 339 call test_autochdir() 340 set autochdir 341 edit Xactual/file.txt 342 call assert_match('testdir.Xactual$', getcwd()) 343 lcd .. 344 call assert_match('testdir$', getcwd()) 345 edit 346 call assert_match('testdir.Xactual$', getcwd()) 347 call assert_match('testdir$', getcwd(win_getid())) 348 349 set noautochdir 350 bwipe! 351 call chdir(startdir) 352 endfunc 353 354 func Test_cd_preserve_symlinks() 355 " Test new behavior: preserve symlinks when cpo-=~ 356 set cpoptions+=~ 357 358 let savedir = getcwd() 359 call mkdir('Xsource', 'R') 360 call writefile(['abc'], 'Xsource/foo.txt', 'D') 361 362 if has("win32") 363 silent !mklink /D Xdest Xsource 364 else 365 silent !ln -s Xsource Xdest 366 endif 367 if v:shell_error 368 call delete('Xsource', 'rf') 369 throw 'Skipped: cannot create symlinks' 370 endif 371 372 edit Xdest/foo.txt 373 let path_before = expand('%') 374 call assert_match('Xdest[/\\]foo\.txt$', path_before) 375 376 cd . 377 let path_after = expand('%') 378 call assert_equal(path_before, path_after) 379 call assert_match('Xdest[/\\]foo\.txt$', path_after) 380 381 bwipe! 382 set cpoptions& 383 call delete('Xdest', 'rf') 384 call delete('Xsource', 'rf') 385 call chdir(savedir) 386 endfunc 387 388 func Test_cd_symlinks() 389 CheckNotMSWindows 390 391 let savedir = getcwd() 392 call mkdir('Xsource', 'R') 393 call writefile(['abc'], 'Xsource/foo.txt', 'D') 394 395 silent !ln -s Xsource Xdest 396 if v:shell_error 397 call delete('Xsource', 'rf') 398 throw 'Skipped: cannot create symlinks' 399 endif 400 401 edit Xdest/foo.txt 402 let path_before = expand('%') 403 call assert_match('Xdest[/\\]foo\.txt$', path_before) 404 405 cd . 406 let path_after = expand('%') 407 call assert_match('Xsource[/\\]foo\.txt$', path_after) 408 call assert_notequal(path_before, path_after) 409 410 bwipe! 411 set cpoptions& 412 call delete('Xdest', 'rf') 413 call delete('Xsource', 'rf') 414 call chdir(savedir) 415 endfunc 416 417 func Test_cd_shorten_bufname_with_duplicate_slashes() 418 let savedir = getcwd() 419 call mkdir('Xexistingdir', 'R') 420 new Xexistingdir//foo/bar 421 cd Xexistingdir 422 call assert_equal('foo/bar', bufname('%')) 423 424 call chdir(savedir) 425 bwipe! 426 endfunc 427 428 " vim: shiftwidth=2 sts=2 expandtab