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
|
-- Other ShaDa tests
local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local t_shada = require('test.functional.shada.testutil')
local uv = vim.uv
local paths = t.paths
local api, nvim_command, fn, eq = n.api, n.command, n.fn, t.eq
local write_file, set_session, exc_exec = t.write_file, n.set_session, n.exc_exec
local is_os = t.is_os
local skip = t.skip
local reset, clear, get_shada_rw = t_shada.reset, t_shada.clear, t_shada.get_shada_rw
local read_shada_file = t_shada.read_shada_file
local wshada, _, shada_fname, clean = get_shada_rw('Xtest-functional-shada-shada.shada')
local dirname = 'Xtest-functional-shada-shada.d'
local dirshada = dirname .. '/main.shada'
describe('ShaDa support code', function()
before_each(reset)
after_each(function()
clear()
clean()
uv.fs_rmdir(dirname)
end)
it('preserves `s` item size limit with unknown entries', function()
wshada(
'\100\000\207\000\000\000\000\000\000\004\000\218\003\253'
.. ('-'):rep(1024 - 3)
.. '\100\000\207\000\000\000\000\000\000\004\001\218\003\254'
.. ('-'):rep(1025 - 3)
)
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 100 then
found = found + 1
end
end
eq(2, found)
eq(0, exc_exec('set shada-=s10 shada+=s1'))
eq(0, exc_exec('wshada ' .. shada_fname))
found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 100 then
found = found + 1
end
end
eq(1, found)
end)
it('preserves `s` item size limit with instance history entries', function()
local hist1 = ('-'):rep(1024 - 5)
local hist2 = ('-'):rep(1025 - 5)
nvim_command('set shada-=s10 shada+=s1')
fn.histadd(':', hist1)
fn.histadd(':', hist2)
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 4 then
found = found + 1
eq(hist1, v.value[2])
end
end
eq(1, found)
end)
it('leaves .tmp.a in-place when there is error in original ShaDa', function()
wshada('Some text file')
eq(
'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier',
exc_exec('wshada ' .. shada_fname)
)
eq(1, read_shada_file(shada_fname .. '.tmp.a')[1].type)
end)
it(
'does not leave .tmp.a in-place when there is error in original ShaDa, but writing with bang',
function()
wshada('Some text file')
eq(0, exc_exec('wshada! ' .. shada_fname))
eq(1, read_shada_file(shada_fname)[1].type)
eq(nil, uv.fs_stat(shada_fname .. '.tmp.a'))
end
)
it('leaves .tmp.b in-place when there is error in original ShaDa and it has .tmp.a', function()
wshada('Some text file')
eq(
'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier',
exc_exec('wshada ' .. shada_fname)
)
eq(
'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier',
exc_exec('wshada ' .. shada_fname)
)
eq(1, read_shada_file(shada_fname .. '.tmp.a')[1].type)
eq(1, read_shada_file(shada_fname .. '.tmp.b')[1].type)
end)
it(
'leaves .tmp.z in-place when there is error in original ShaDa and it has .tmp.a … .tmp.x',
function()
wshada('Some text file')
local i = ('a'):byte()
while i < ('z'):byte() do
write_file(shada_fname .. ('.tmp.%c'):format(i), 'Some text file', true)
i = i + 1
end
eq(
'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier',
exc_exec('wshada ' .. shada_fname)
)
eq(1, read_shada_file(shada_fname .. '.tmp.z')[1].type)
end
)
it('errors out when there are .tmp.a … .tmp.z ShaDa files', function()
wshada('')
local i = ('a'):byte()
while i <= ('z'):byte() do
write_file(shada_fname .. ('.tmp.%c'):format(i), '', true)
i = i + 1
end
eq(
'Vim(wshada):E138: All Xtest-functional-shada-shada.shada.tmp.X files exist, cannot write ShaDa file!',
exc_exec('wshada ' .. shada_fname)
)
end)
it('reads correctly various timestamps', function()
local msgpack = {
'\100', -- Positive fixnum 100
'\204\255', -- uint 8 255
'\205\010\003', -- uint 16 2563
'\206\255\010\030\004', -- uint 32 4278853124
'\207\005\100\060\250\255\010\030\004', -- uint 64 388502516579048964
}
local s = '\100'
local e = '\001\192'
wshada(s .. table.concat(msgpack, e .. s) .. e)
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
local typ = vim.mpack.decode(s)
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == typ then
found = found + 1
eq(vim.mpack.decode(msgpack[found]), v.timestamp)
end
end
eq(#msgpack, found)
end)
local marklike = { [7] = true, [8] = true, [10] = true, [11] = true }
local find_file = function(fname)
local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
if marklike[v.type] and v.value.f == fname then
found[v.type] = (found[v.type] or 0) + 1
elseif v.type == 9 then
for _, b in ipairs(v.value) do
if b.f == fname then
found[v.type] = (found[v.type] or 0) + 1
end
end
end
end
return found
end
it('correctly uses shada-r option', function()
nvim_command('set shellslash')
api.nvim_set_var('__home', paths.test_source_path)
nvim_command('let $HOME = __home')
nvim_command('unlet __home')
nvim_command('edit ~/README.md')
nvim_command('normal! GmAggmaAabc')
nvim_command('undo')
nvim_command('set shada+=%')
nvim_command('wshada! ' .. shada_fname)
local readme_fname = fn.resolve(paths.test_source_path) .. '/README.md'
eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 1 }, find_file(readme_fname))
nvim_command('set shada+=r~')
nvim_command('wshada! ' .. shada_fname)
eq({}, find_file(readme_fname))
nvim_command('set shada-=r~')
nvim_command('wshada! ' .. shada_fname)
eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 1 }, find_file(readme_fname))
nvim_command('set shada+=r' .. fn.escape(fn.escape(paths.test_source_path, '$~'), ' "\\,'))
nvim_command('wshada! ' .. shada_fname)
eq({}, find_file(readme_fname))
end)
it('correctly ignores case with shada-r option', function()
nvim_command('set shellslash')
local pwd = fn.getcwd()
local relfname = 'абв/test'
local fname = pwd .. '/' .. relfname
api.nvim_set_var('__fname', fname)
nvim_command('silent! edit `=__fname`')
fn.setline(1, { 'a', 'b', 'c', 'd' })
nvim_command('normal! GmAggmaAabc')
nvim_command('undo')
nvim_command('set shada+=%')
nvim_command('wshada! ' .. shada_fname)
eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 2 }, find_file(fname))
nvim_command('set shada+=r' .. pwd .. '/АБВ')
nvim_command('wshada! ' .. shada_fname)
eq({}, find_file(fname))
end)
it('is able to set &shada after &viminfo', function()
api.nvim_set_option_value('viminfo', "'10", {})
eq("'10", api.nvim_get_option_value('viminfo', {}))
eq("'10", api.nvim_get_option_value('shada', {}))
api.nvim_set_option_value('shada', '', {})
eq('', api.nvim_get_option_value('viminfo', {}))
eq('', api.nvim_get_option_value('shada', {}))
end)
it('is able to set all& after setting &shada', function()
api.nvim_set_option_value('shada', "'10", {})
eq("'10", api.nvim_get_option_value('viminfo', {}))
eq("'10", api.nvim_get_option_value('shada', {}))
nvim_command('set all&')
eq("!,'100,<50,s10,h", api.nvim_get_option_value('viminfo', {}))
eq("!,'100,<50,s10,h", api.nvim_get_option_value('shada', {}))
end)
it('is able to set &shada after &viminfo using :set', function()
nvim_command("set viminfo='10")
eq("'10", api.nvim_get_option_value('viminfo', {}))
eq("'10", api.nvim_get_option_value('shada', {}))
nvim_command('set shada=')
eq('', api.nvim_get_option_value('viminfo', {}))
eq('', api.nvim_get_option_value('shada', {}))
end)
it('setting &shada gives proper error message on missing number', function()
eq([[Vim(set):E526: Missing number after <">: shada="]], exc_exec([[set shada=\"]]))
for _, c in ipairs({ "'", '/', ':', '<', '@', 's' }) do
eq(
([[Vim(set):E526: Missing number after <%s>: shada=%s]]):format(c, c),
exc_exec(([[set shada=%s]]):format(c))
)
end
end)
it('does not crash when ShaDa file directory is not writable', function()
skip(is_os('win'))
fn.mkdir(dirname, '', '0')
eq(0, fn.filewritable(dirname))
reset { shadafile = dirshada, args = { '--cmd', 'set shada=' } }
api.nvim_set_option_value('shada', "'10", {})
eq(
'Vim(wshada):E886: System error while opening ShaDa file '
.. 'Xtest-functional-shada-shada.d/main.shada for reading to merge '
.. 'before writing it: permission denied',
exc_exec('wshada')
)
api.nvim_set_option_value('shada', '', {})
end)
end)
describe('ShaDa support code', function()
it('does not write NONE file', function()
local session = n.new_session(false, {
merge = false,
args = { '-u', 'NONE', '-i', 'NONE', '--embed', '--headless', '--cmd', 'qall' },
})
session:close()
eq(nil, uv.fs_stat('NONE'))
eq(nil, uv.fs_stat('NONE.tmp.a'))
end)
it('does not read NONE file', function()
write_file('NONE', '\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
local session = n.new_session(
false,
{ merge = false, args = { '-u', 'NONE', '-i', 'NONE', '--embed', '--headless' } }
)
set_session(session)
eq('', fn.getreg('a'))
session:close()
os.remove('NONE')
end)
end)
|