1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
|
{:cimport, :internalize, :eq, :neq, :ffi, :lib, :cstr, :to_cstr, :NULL, :OK, :FAIL} = require 'test.unit.helpers'
require 'lfs'
path = cimport './src/nvim/path.h'
-- import constants parsed by ffi
{:kEqualFiles, :kDifferentFiles, :kBothFilesMissing, :kOneFileMissing, :kEqualFileNames} = path
describe 'path function', ->
describe 'path_full_dir_name', ->
setup ->
lfs.mkdir 'unit-test-directory'
teardown ->
lfs.rmdir 'unit-test-directory'
path_full_dir_name = (directory, buffer, len) ->
directory = to_cstr directory
path.path_full_dir_name directory, buffer, len
before_each ->
-- Create empty string buffer which will contain the resulting path.
export len = (string.len lfs.currentdir!) + 22
export buffer = cstr len, ''
it 'returns the absolute directory name of a given relative one', ->
result = path_full_dir_name '..', buffer, len
eq OK, result
old_dir = lfs.currentdir!
lfs.chdir '..'
expected = lfs.currentdir!
lfs.chdir old_dir
eq expected, (ffi.string buffer)
it 'returns the current directory name if the given string is empty', ->
eq OK, (path_full_dir_name '', buffer, len)
eq lfs.currentdir!, (ffi.string buffer)
it 'fails if the given directory does not exist', ->
eq FAIL, path_full_dir_name('does_not_exist', buffer, len)
it 'works with a normal relative dir', ->
result = path_full_dir_name('unit-test-directory', buffer, len)
eq lfs.currentdir! .. '/unit-test-directory', (ffi.string buffer)
eq OK, result
describe 'path_full_compare', ->
path_full_compare = (s1, s2, cn) ->
s1 = to_cstr s1
s2 = to_cstr s2
path.path_full_compare s1, s2, cn or 0
f1 = 'f1.o'
f2 = 'f2.o'
before_each ->
-- create the three files that will be used in this spec
(io.open f1, 'w').close!
(io.open f2, 'w').close!
after_each ->
os.remove f1
os.remove f2
it 'returns kEqualFiles when passed the same file', ->
eq kEqualFiles, (path_full_compare f1, f1)
it 'returns kEqualFileNames when files that dont exist and have same name', ->
eq kEqualFileNames, (path_full_compare 'null.txt', 'null.txt', true)
it 'returns kBothFilesMissing when files that dont exist', ->
eq kBothFilesMissing, (path_full_compare 'null.txt', 'null.txt')
it 'returns kDifferentFiles when passed different files', ->
eq kDifferentFiles, (path_full_compare f1, f2)
eq kDifferentFiles, (path_full_compare f2, f1)
it 'returns kOneFileMissing if only one does not exist', ->
eq kOneFileMissing, (path_full_compare f1, 'null.txt')
eq kOneFileMissing, (path_full_compare 'null.txt', f1)
describe 'path_tail', ->
path_tail = (file) ->
res = path.path_tail (to_cstr file)
neq NULL, res
ffi.string res
it 'returns the tail of a given file path', ->
eq 'file.txt', path_tail 'directory/file.txt'
it 'returns an empty string if file ends in a slash', ->
eq '', path_tail 'directory/'
describe 'path_tail_with_sep', ->
path_tail_with_sep = (file) ->
res = path.path_tail_with_sep (to_cstr file)
neq NULL, res
ffi.string res
it 'returns the tail of a file together with its separator', ->
eq '///file.txt', path_tail_with_sep 'directory///file.txt'
it 'returns an empty string when given an empty file name', ->
eq '', path_tail_with_sep ''
it 'returns only the separator if there is a trailing separator', ->
eq '/', path_tail_with_sep 'some/directory/'
it 'cuts a leading separator', ->
eq 'file.txt', path_tail_with_sep '/file.txt'
eq '', path_tail_with_sep '/'
it 'returns the whole file name if there is no separator', ->
eq 'file.txt', path_tail_with_sep 'file.txt'
describe 'path_next_component', ->
path_next_component = (file) ->
res = path.path_next_component (to_cstr file)
neq NULL, res
ffi.string res
it 'returns', ->
eq 'directory/file.txt', path_next_component 'some/directory/file.txt'
it 'returns empty string if given file contains no separator', ->
eq '', path_next_component 'file.txt'
describe 'path_shorten_fname', ->
it 'returns NULL if `full_path` is NULL', ->
dir = to_cstr 'some/directory/file.txt'
eq NULL, (path.path_shorten_fname NULL, dir)
it 'returns NULL if the path and dir does not match', ->
dir = to_cstr 'not/the/same'
full = to_cstr 'as/this.txt'
eq NULL, (path.path_shorten_fname full, dir)
it 'returns NULL if the path is not separated properly', ->
dir = to_cstr 'some/very/long/'
full = to_cstr 'some/very/long/directory/file.txt'
eq NULL, (path.path_shorten_fname full, dir)
it 'shortens the filename if `dir_name` is the start of `full_path`', ->
full = to_cstr 'some/very/long/directory/file.txt'
dir = to_cstr 'some/very/long'
eq 'directory/file.txt', (ffi.string path.path_shorten_fname full, dir)
describe 'path_shorten_fname_if_possible', ->
cwd = lfs.currentdir!
before_each ->
lfs.mkdir 'ut_directory'
after_each ->
lfs.chdir cwd
lfs.rmdir 'ut_directory'
describe 'path_shorten_fname_if_possible', ->
it 'returns shortened path if possible', ->
lfs.chdir 'ut_directory'
full = to_cstr lfs.currentdir! .. '/subdir/file.txt'
eq 'subdir/file.txt', (ffi.string path.path_shorten_fname_if_possible full)
it 'returns `full_path` if a shorter version is not possible', ->
old = lfs.currentdir!
lfs.chdir 'ut_directory'
full = old .. '/subdir/file.txt'
eq full, (ffi.string path.path_shorten_fname_if_possible to_cstr full)
it 'returns NULL if `full_path` is NULL', ->
eq NULL, (path.path_shorten_fname_if_possible NULL)
describe 'more path function', ->
setup ->
lfs.mkdir 'unit-test-directory'
(io.open 'unit-test-directory/test.file', 'w').close!
-- Since the tests are executed, they are called by an executable. We use
-- that executable for several asserts.
export absolute_executable = arg[0]
-- Split absolute_executable into a directory and the actual file name for
-- later usage.
export directory, executable_name = string.match(absolute_executable, '^(.*)/(.*)$')
teardown ->
os.remove 'unit-test-directory/test.file'
lfs.rmdir 'unit-test-directory'
describe 'vim_FullName', ->
vim_FullName = (filename, buffer, length, force) ->
filename = to_cstr filename
path.vim_FullName filename, buffer, length, force
before_each ->
-- Create empty string buffer which will contain the resulting path.
export len = (string.len lfs.currentdir!) + 33
export buffer = cstr len, ''
it 'fails if given filename is NULL', ->
force_expansion = 1
result = path.vim_FullName NULL, buffer, len, force_expansion
eq FAIL, result
it 'uses the filename if the filename is a URL', ->
force_expansion = 1
filename = 'http://www.neovim.org'
result = vim_FullName filename, buffer, len, force_expansion
eq filename, (ffi.string buffer)
eq OK, result
it 'fails and uses filename if given filename contains non-existing directory', ->
force_expansion = 1
filename = 'non_existing_dir/test.file'
result = vim_FullName filename, buffer, len, force_expansion
eq filename, (ffi.string buffer)
eq FAIL, result
it 'concatenates given filename if it does not contain a slash', ->
force_expansion = 1
result = vim_FullName 'test.file', buffer, len, force_expansion
expected = lfs.currentdir! .. '/test.file'
eq expected, (ffi.string buffer)
eq OK, result
it 'concatenates given filename if it is a directory but does not contain a
slash', ->
force_expansion = 1
result = vim_FullName '..', buffer, len, force_expansion
expected = lfs.currentdir! .. '/..'
eq expected, (ffi.string buffer)
eq OK, result
-- Is it possible for every developer to enter '..' directory while running
-- the unit tests? Which other directory would be better?
it 'enters given directory (instead of just concatenating the strings) if
possible and if path contains a slash', ->
force_expansion = 1
result = vim_FullName '../test.file', buffer, len, force_expansion
old_dir = lfs.currentdir!
lfs.chdir '..'
expected = lfs.currentdir! .. '/test.file'
lfs.chdir old_dir
eq expected, (ffi.string buffer)
eq OK, result
it 'just copies the path if it is already absolute and force=0', ->
force_expansion = 0
absolute_path = '/absolute/path'
result = vim_FullName absolute_path, buffer, len, force_expansion
eq absolute_path, (ffi.string buffer)
eq OK, result
it 'fails and uses filename when the path is relative to HOME', ->
force_expansion = 1
absolute_path = '~/home.file'
result = vim_FullName absolute_path, buffer, len, force_expansion
eq absolute_path, (ffi.string buffer)
eq FAIL, result
it 'works with some "normal" relative path with directories', ->
force_expansion = 1
result = vim_FullName 'unit-test-directory/test.file', buffer, len, force_expansion
eq OK, result
eq lfs.currentdir! .. '/unit-test-directory/test.file', (ffi.string buffer)
it 'does not modify the given filename', ->
force_expansion = 1
filename = to_cstr 'unit-test-directory/test.file'
-- Don't use the wrapper here but pass a cstring directly to the c
-- function.
result = path.vim_FullName filename, buffer, len, force_expansion
eq lfs.currentdir! .. '/unit-test-directory/test.file', (ffi.string buffer)
eq 'unit-test-directory/test.file', (ffi.string filename)
eq OK, result
describe 'append_path', ->
it 'joins given paths with a slash', ->
path1 = cstr 100, 'path1'
to_append = to_cstr 'path2'
eq OK, (path.append_path path1, to_append, 100)
eq "path1/path2", (ffi.string path1)
it 'joins given paths without adding an unnecessary slash', ->
path1 = cstr 100, 'path1/'
to_append = to_cstr 'path2'
eq OK, path.append_path path1, to_append, 100
eq "path1/path2", (ffi.string path1)
it 'fails and uses filename if there is not enough space left for to_append', ->
path1 = cstr 11, 'path1/'
to_append = to_cstr 'path2'
eq FAIL, (path.append_path path1, to_append, 11)
it 'does not append a slash if to_append is empty', ->
path1 = cstr 6, 'path1'
to_append = to_cstr ''
eq OK, (path.append_path path1, to_append, 6)
eq 'path1', (ffi.string path1)
it 'does not append unnecessary dots', ->
path1 = cstr 6, 'path1'
to_append = to_cstr '.'
eq OK, (path.append_path path1, to_append, 6)
eq 'path1', (ffi.string path1)
it 'copies to_append to path, if path is empty', ->
path1 = cstr 7, ''
to_append = to_cstr '/path2'
eq OK, (path.append_path path1, to_append, 7)
eq '/path2', (ffi.string path1)
describe 'path_is_absolute_path', ->
path_is_absolute_path = (filename) ->
filename = to_cstr filename
path.path_is_absolute_path filename
it 'returns true if filename starts with a slash', ->
eq OK, path_is_absolute_path '/some/directory/'
it 'returns true if filename starts with a tilde', ->
eq OK, path_is_absolute_path '~/in/my/home~/directory'
it 'returns false if filename starts not with slash nor tilde', ->
eq FAIL, path_is_absolute_path 'not/in/my/home~/directory'
|