diff options
author | Hisham Muhammad <hisham@gobolinux.org> | 2024-02-26 17:47:28 -0300 |
---|---|---|
committer | Hisham Muhammad <hisham@gobolinux.org> | 2024-02-27 13:28:33 -0300 |
commit | 5cba4b83f60966045b86ac615df2692c953ebba7 (patch) | |
tree | 445d1f58e589b53e4ee8cda5984f430f54fd2b36 /spec/unit | |
parent | 6bc6ede826843c3692971c14c27c3d27714b2126 (diff) | |
download | luarocks-5cba4b83f60966045b86ac615df2692c953ebba7.tar.gz luarocks-5cba4b83f60966045b86ac615df2692c953ebba7.tar.bz2 luarocks-5cba4b83f60966045b86ac615df2692c953ebba7.zip |
fix(fs): make current_dir always return 1 arg only
Diffstat (limited to 'spec/unit')
-rw-r--r-- | spec/unit/build_spec.lua | 369 | ||||
-rw-r--r-- | spec/unit/dir_spec.lua | 72 | ||||
-rw-r--r-- | spec/unit/fetch_spec.lua | 488 | ||||
-rw-r--r-- | spec/unit/fs_spec.lua | 1607 | ||||
-rw-r--r-- | spec/unit/fun_spec.lua | 130 | ||||
-rw-r--r-- | spec/unit/persist_spec.lua | 76 | ||||
-rw-r--r-- | spec/unit/rockspecs_spec.lua | 126 | ||||
-rw-r--r-- | spec/unit/sysdetect_spec.lua | 75 | ||||
-rw-r--r-- | spec/unit/tools_spec.lua | 253 |
9 files changed, 3196 insertions, 0 deletions
diff --git a/spec/unit/build_spec.lua b/spec/unit/build_spec.lua new file mode 100644 index 00000000..6ab143c6 --- /dev/null +++ b/spec/unit/build_spec.lua | |||
@@ -0,0 +1,369 @@ | |||
1 | local test_env = require("spec.util.test_env") | ||
2 | local lfs = require("lfs") | ||
3 | local get_tmp_path = test_env.get_tmp_path | ||
4 | local run = test_env.run | ||
5 | local testing_paths = test_env.testing_paths | ||
6 | local write_file = test_env.write_file | ||
7 | local P = test_env.P | ||
8 | |||
9 | test_env.unload_luarocks() | ||
10 | |||
11 | test_env.unload_luarocks() | ||
12 | test_env.setup_specs() | ||
13 | local cfg = require("luarocks.core.cfg") | ||
14 | local deps = require("luarocks.deps") | ||
15 | local fs = require("luarocks.fs") | ||
16 | local path = require("luarocks.path") | ||
17 | local rockspecs = require("luarocks.rockspecs") | ||
18 | local build_builtin = require("luarocks.build.builtin") | ||
19 | |||
20 | local c_module_source = [[ | ||
21 | #include <lua.h> | ||
22 | #include <lauxlib.h> | ||
23 | |||
24 | int luaopen_c_module(lua_State* L) { | ||
25 | lua_newtable(L); | ||
26 | lua_pushinteger(L, 1); | ||
27 | lua_setfield(L, -2, "c_module"); | ||
28 | return 1; | ||
29 | } | ||
30 | ]] | ||
31 | |||
32 | describe("LuaRocks build #unit", function() | ||
33 | local runner | ||
34 | |||
35 | lazy_setup(function() | ||
36 | runner = require("luacov.runner") | ||
37 | runner.init(testing_paths.testrun_dir .. "/luacov.config") | ||
38 | runner.tick = true | ||
39 | cfg.init() | ||
40 | fs.init() | ||
41 | deps.check_lua_incdir(cfg.variables) | ||
42 | deps.check_lua_libdir(cfg.variables) | ||
43 | end) | ||
44 | |||
45 | lazy_teardown(function() | ||
46 | runner.shutdown() | ||
47 | end) | ||
48 | |||
49 | describe("build.builtin", function() | ||
50 | it("builtin auto installs files in lua subdir", function() | ||
51 | test_env.run_in_tmp(function(tmpdir) | ||
52 | lfs.mkdir("lua") | ||
53 | write_file("lua_module-1.0-1.rockspec", [[ | ||
54 | package = "lua_module" | ||
55 | version = "1.0-1" | ||
56 | source = { | ||
57 | url = "http://example.com/lua_module" | ||
58 | } | ||
59 | build = { | ||
60 | type = "builtin", | ||
61 | modules = {} | ||
62 | } | ||
63 | ]], finally) | ||
64 | write_file("lua/lua_module.lua", "return 123", finally) | ||
65 | |||
66 | assert.is_true(run.luarocks_bool("build")) | ||
67 | assert.match("[\\/]lua_module%.lua", run.luarocks("show lua_module")) | ||
68 | end, finally) | ||
69 | end) | ||
70 | |||
71 | describe("builtin.autodetect_modules", function() | ||
72 | local tmpdir | ||
73 | local olddir | ||
74 | |||
75 | before_each(function() | ||
76 | tmpdir = get_tmp_path() | ||
77 | olddir = lfs.currentdir() | ||
78 | lfs.mkdir(tmpdir) | ||
79 | lfs.chdir(tmpdir) | ||
80 | fs.change_dir(tmpdir) | ||
81 | end) | ||
82 | |||
83 | after_each(function() | ||
84 | if olddir then | ||
85 | lfs.chdir(olddir) | ||
86 | fs.change_dir(olddir) | ||
87 | if tmpdir then | ||
88 | lfs.rmdir(tmpdir) | ||
89 | end | ||
90 | end | ||
91 | end) | ||
92 | |||
93 | local libs = { "foo1", "foo2" } | ||
94 | local incdirs = { "$(FOO1_INCDIR)", "$(FOO2_INCDIR)" } | ||
95 | local libdirs = { "$(FOO1_LIBDIR)", "$(FOO2_LIBDIR)" } | ||
96 | |||
97 | it("returns a table of the modules having as location the current directory", function() | ||
98 | write_file("module1.lua", "", finally) | ||
99 | write_file("module2.c", "", finally) | ||
100 | write_file("module3.c", "int luaopen_my_module()", finally) | ||
101 | write_file("test.lua", "", finally) | ||
102 | write_file("tests.lua", "", finally) | ||
103 | |||
104 | local modules = build_builtin.autodetect_modules(libs, incdirs, libdirs) | ||
105 | assert.same(modules, { | ||
106 | module1 = "module1.lua", | ||
107 | module2 = { | ||
108 | sources = "module2.c", | ||
109 | libraries = libs, | ||
110 | incdirs = incdirs, | ||
111 | libdirs = libdirs | ||
112 | }, | ||
113 | my_module = { | ||
114 | sources = "module3.c", | ||
115 | libraries = libs, | ||
116 | incdirs = incdirs, | ||
117 | libdirs = libdirs | ||
118 | } | ||
119 | }) | ||
120 | end) | ||
121 | |||
122 | local test_with_location = function(location) | ||
123 | lfs.mkdir(location) | ||
124 | lfs.mkdir(location .. "/dir1") | ||
125 | lfs.mkdir(location .. "/dir1/dir2") | ||
126 | |||
127 | write_file(location .. "/module1.lua", "", finally) | ||
128 | write_file(location .. "/dir1/module2.c", "", finally) | ||
129 | write_file(location .. "/dir1/dir2/module3.c", "int luaopen_my_module()", finally) | ||
130 | write_file(location .. "/test.lua", "", finally) | ||
131 | write_file(location .. "/tests.lua", "", finally) | ||
132 | |||
133 | local modules = build_builtin.autodetect_modules(libs, incdirs, libdirs) | ||
134 | assert.same(modules, { | ||
135 | module1 = location .. "/module1.lua", | ||
136 | ["dir1.module2"] = { | ||
137 | sources = location .. "/dir1/module2.c", | ||
138 | libraries = libs, | ||
139 | incdirs = incdirs, | ||
140 | libdirs = libdirs | ||
141 | }, | ||
142 | my_module = { | ||
143 | sources = location .. "/dir1/dir2/module3.c", | ||
144 | libraries = libs, | ||
145 | incdirs = incdirs, | ||
146 | libdirs = libdirs | ||
147 | } | ||
148 | }) | ||
149 | |||
150 | lfs.rmdir(location .. "/dir1/dir2") | ||
151 | lfs.rmdir(location .. "/dir1") | ||
152 | lfs.rmdir(location) | ||
153 | end | ||
154 | |||
155 | it("returns a table of the modules having as location the src directory", function() | ||
156 | test_with_location("src") | ||
157 | end) | ||
158 | |||
159 | it("returns a table of the modules having as location the lua directory", function() | ||
160 | test_with_location("lua") | ||
161 | end) | ||
162 | |||
163 | it("returns as second and third argument tables of the bin files and copy directories", function() | ||
164 | lfs.mkdir("doc") | ||
165 | lfs.mkdir("docs") | ||
166 | lfs.mkdir("samples") | ||
167 | lfs.mkdir("tests") | ||
168 | lfs.mkdir("bin") | ||
169 | write_file("bin/binfile", "", finally) | ||
170 | |||
171 | local _, install, copy_directories = build_builtin.autodetect_modules({}, {}, {}) | ||
172 | assert.same(install, { bin = { P"bin/binfile" } }) | ||
173 | assert.same(copy_directories, { "doc", "docs", "samples", "tests" }) | ||
174 | |||
175 | lfs.rmdir("doc") | ||
176 | lfs.rmdir("docs") | ||
177 | lfs.rmdir("samples") | ||
178 | lfs.rmdir("tests") | ||
179 | lfs.rmdir("bin") | ||
180 | end) | ||
181 | end) | ||
182 | |||
183 | describe("builtin.run", function() | ||
184 | local tmpdir | ||
185 | local olddir | ||
186 | |||
187 | before_each(function() | ||
188 | tmpdir = get_tmp_path() | ||
189 | olddir = lfs.currentdir() | ||
190 | lfs.mkdir(tmpdir) | ||
191 | lfs.chdir(tmpdir) | ||
192 | fs.change_dir(tmpdir) | ||
193 | path.use_tree(lfs.currentdir()) | ||
194 | end) | ||
195 | |||
196 | after_each(function() | ||
197 | if olddir then | ||
198 | lfs.chdir(olddir) | ||
199 | fs.change_dir(olddir) | ||
200 | if tmpdir then | ||
201 | lfs.rmdir(tmpdir) | ||
202 | end | ||
203 | end | ||
204 | end) | ||
205 | |||
206 | it("returns false if the rockspec has no build modules and its format does not support autoextraction", function() | ||
207 | local rockspec = { | ||
208 | package = "test", | ||
209 | version = "1.0-1", | ||
210 | source = { | ||
211 | url = "http://example.com/test" | ||
212 | }, | ||
213 | build = {} | ||
214 | } | ||
215 | |||
216 | rockspecs.from_persisted_table("test-1.0-1.rockspec", rockspec) | ||
217 | assert.falsy(build_builtin.run(rockspec)) | ||
218 | rockspec.rockspec_format = "1.0" | ||
219 | assert.falsy(build_builtin.run(rockspec)) | ||
220 | end) | ||
221 | |||
222 | it("returns false if lua.h could not be found", function() | ||
223 | local rockspec = { | ||
224 | package = "c_module", | ||
225 | version = "1.0-1", | ||
226 | source = { | ||
227 | url = "http://example.com/c_module" | ||
228 | }, | ||
229 | build = { | ||
230 | type = "builtin", | ||
231 | modules = { | ||
232 | c_module = "c_module.c" | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | write_file("c_module.c", c_module_source, finally) | ||
237 | |||
238 | rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) | ||
239 | rockspec.variables = { LUA_INCDIR = "invalid" } | ||
240 | assert.falsy(build_builtin.run(rockspec)) | ||
241 | end) | ||
242 | |||
243 | it("returns false if the build fails", function() | ||
244 | local rockspec = { | ||
245 | package = "c_module", | ||
246 | version = "1.0-1", | ||
247 | source = { | ||
248 | url = "http://example.com/c_module" | ||
249 | }, | ||
250 | build = { | ||
251 | type = "builtin", | ||
252 | modules = { | ||
253 | c_module = "c_module.c" | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | write_file("c_module.c", c_module_source .. "invalid", finally) | ||
258 | |||
259 | rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) | ||
260 | assert.falsy(build_builtin.run(rockspec)) | ||
261 | end) | ||
262 | |||
263 | it("returns true if the build succeeds with C module", function() | ||
264 | local rockspec = { | ||
265 | package = "c_module", | ||
266 | version = "1.0-1", | ||
267 | source = { | ||
268 | url = "http://example.com/c_module" | ||
269 | }, | ||
270 | build = { | ||
271 | type = "builtin", | ||
272 | modules = { | ||
273 | c_module = "c_module.c" | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | write_file("c_module.c", c_module_source, finally) | ||
278 | |||
279 | rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) | ||
280 | assert.truthy(build_builtin.run(rockspec)) | ||
281 | assert.truthy(lfs.attributes("lib/luarocks/rocks-" .. test_env.lua_version .. "/c_module/1.0-1/lib/c_module." .. test_env.lib_extension)) | ||
282 | end) | ||
283 | |||
284 | it("returns true if the build succeeds with Lua module", function() | ||
285 | local rockspec = { | ||
286 | rockspec_format = "1.0", | ||
287 | package = "test", | ||
288 | version = "1.0-1", | ||
289 | source = { | ||
290 | url = "http://example.com/test" | ||
291 | }, | ||
292 | build = { | ||
293 | type = "builtin", | ||
294 | modules = { | ||
295 | test = "test.lua" | ||
296 | } | ||
297 | } | ||
298 | } | ||
299 | write_file("test.lua", "return {}", finally) | ||
300 | |||
301 | rockspecs.from_persisted_table("test-1.0-1.rockspec", rockspec) | ||
302 | assert.truthy(build_builtin.run(rockspec)) | ||
303 | assert.truthy(lfs.attributes("lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/lua/test.lua")) | ||
304 | end) | ||
305 | |||
306 | it("automatically extracts the modules and libraries if they are not given and builds against any external dependencies", function() | ||
307 | local fdir = testing_paths.fixtures_dir | ||
308 | if test_env.TEST_TARGET_OS == "windows" then | ||
309 | if test_env.MINGW then | ||
310 | os.execute("gcc -shared -o " .. fdir .. "/libfixturedep.dll -Wl,--out-implib," .. fdir .."/libfixturedep.a " .. fdir .. "/fixturedep.c") | ||
311 | else | ||
312 | os.execute("cl " .. fdir .. "\\fixturedep.c /link /export:fixturedep_fn /out:" .. fdir .. "\\fixturedep.dll /implib:" .. fdir .. "\\fixturedep.lib") | ||
313 | end | ||
314 | elseif test_env.TEST_TARGET_OS == "linux" then | ||
315 | os.execute("gcc -shared -o " .. fdir .. "/libfixturedep.so " .. fdir .. "/fixturedep.c") | ||
316 | elseif test_env.TEST_TARGET_OS == "osx" then | ||
317 | os.execute("cc -dynamiclib -o " .. fdir .. "/libfixturedep.dylib " .. fdir .. "/fixturedep.c") | ||
318 | end | ||
319 | |||
320 | local rockspec = { | ||
321 | rockspec_format = "3.0", | ||
322 | package = "c_module", | ||
323 | version = "1.0-1", | ||
324 | source = { | ||
325 | url = "http://example.com/c_module" | ||
326 | }, | ||
327 | external_dependencies = { | ||
328 | FIXTUREDEP = { | ||
329 | library = "fixturedep" | ||
330 | } | ||
331 | }, | ||
332 | build = { | ||
333 | type = "builtin" | ||
334 | } | ||
335 | } | ||
336 | write_file("c_module.c", c_module_source, finally) | ||
337 | |||
338 | rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) | ||
339 | rockspec.variables["FIXTUREDEP_LIBDIR"] = testing_paths.fixtures_dir | ||
340 | assert.truthy(build_builtin.run(rockspec)) | ||
341 | end) | ||
342 | |||
343 | it("returns false if any external dependency is missing", function() | ||
344 | local rockspec = { | ||
345 | rockspec_format = "3.0", | ||
346 | package = "c_module", | ||
347 | version = "1.0-1", | ||
348 | source = { | ||
349 | url = "https://example.com/c_module" | ||
350 | }, | ||
351 | external_dependencies = { | ||
352 | EXTDEP = { | ||
353 | library = "missing" | ||
354 | } | ||
355 | }, | ||
356 | build = { | ||
357 | type = "builtin" | ||
358 | } | ||
359 | } | ||
360 | write_file("c_module.c", c_module_source, finally) | ||
361 | |||
362 | rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) | ||
363 | rockspec.variables["EXTDEP_INCDIR"] = lfs.currentdir() | ||
364 | rockspec.variables["EXTDEP_LIBDIR"] = lfs.currentdir() | ||
365 | assert.falsy(build_builtin.run(rockspec)) | ||
366 | end) | ||
367 | end) | ||
368 | end) | ||
369 | end) | ||
diff --git a/spec/unit/dir_spec.lua b/spec/unit/dir_spec.lua new file mode 100644 index 00000000..b5dadda8 --- /dev/null +++ b/spec/unit/dir_spec.lua | |||
@@ -0,0 +1,72 @@ | |||
1 | local test_env = require("spec.util.test_env") | ||
2 | local testing_paths = test_env.testing_paths | ||
3 | local P = test_env.P | ||
4 | |||
5 | test_env.unload_luarocks() | ||
6 | test_env.setup_specs() | ||
7 | local dir = require("luarocks.dir") | ||
8 | |||
9 | describe("luarocks.dir #unit", function() | ||
10 | local runner | ||
11 | |||
12 | setup(function() | ||
13 | runner = require("luacov.runner") | ||
14 | runner.init(testing_paths.testrun_dir .. "/luacov.config") | ||
15 | runner.tick = true | ||
16 | end) | ||
17 | |||
18 | teardown(function() | ||
19 | runner.shutdown() | ||
20 | end) | ||
21 | |||
22 | describe("dir.is_basic_protocol", function() | ||
23 | it("checks whether the arguments represent a valid protocol and returns the result of the check", function() | ||
24 | assert.truthy(dir.is_basic_protocol("http")) | ||
25 | assert.truthy(dir.is_basic_protocol("https")) | ||
26 | assert.truthy(dir.is_basic_protocol("ftp")) | ||
27 | assert.truthy(dir.is_basic_protocol("file")) | ||
28 | assert.falsy(dir.is_basic_protocol("git")) | ||
29 | assert.falsy(dir.is_basic_protocol("git+https")) | ||
30 | assert.falsy(dir.is_basic_protocol("invalid")) | ||
31 | end) | ||
32 | end) | ||
33 | |||
34 | describe("dir.deduce_base_dir", function() | ||
35 | it("deduces the base dir from archives", function() | ||
36 | assert.are.same("v0.3", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2/archive/v0.3.zip")) | ||
37 | assert.are.same("lua-compat-5.2", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2.zip")) | ||
38 | assert.are.same("lua-compat-5.2", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2.tar.gz")) | ||
39 | assert.are.same("lua-compat-5.2", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2.tar.bz2")) | ||
40 | end) | ||
41 | it("returns the basename when not given an archive", function() | ||
42 | assert.are.same("parser.moon", dir.deduce_base_dir("git://example.com/Cirru/parser.moon")) | ||
43 | assert.are.same("v0.3", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2/archive/v0.3")) | ||
44 | end) | ||
45 | end) | ||
46 | |||
47 | describe("dir.normalize", function() | ||
48 | it("converts backslashes and removes trailing slashes", function() | ||
49 | assert.are.same(P"/foo/ovo", dir.normalize("\\foo\\ovo\\")) | ||
50 | assert.are.same(P"c:/some/dir", dir.normalize("c:\\..\\some\\foo\\..\\dir")) | ||
51 | assert.are.same("http://example.com/foo/ovo", dir.normalize("http://example.com/foo\\ovo\\")) | ||
52 | end) | ||
53 | it("strips unneeded /../ and /./", function() | ||
54 | assert.are.same(P"/some/dir/file.txt", dir.normalize("/../../../some/./foo/bar/.././../dir/bla/../file.txt")) | ||
55 | assert.are.same(P"/some/dir/file.txt", dir.normalize("/../../../some/./foo/bar/.././../dir/bla/../file.txt")) | ||
56 | assert.are.same(P"/some/dir", dir.normalize("/../../../some/./foo/bar/.././../dir/./some/subdir/../..")) | ||
57 | assert.are.same(P"/some/dir", dir.normalize("/../../../some/./foo/bar/.././../dir/./.")) | ||
58 | end) | ||
59 | it("respects relative paths", function() | ||
60 | assert.are.same(P".", dir.normalize(".")) | ||
61 | assert.are.same(P"boo", dir.normalize("./boo")) | ||
62 | assert.are.same(P"/boo", dir.normalize("/./boo")) | ||
63 | assert.are.same(P"../../../../boo", dir.normalize("../../../hello/world/../../../boo")) | ||
64 | end) | ||
65 | it("respects root directory", function() | ||
66 | assert.are.same(P"/", dir.normalize("/")) | ||
67 | assert.are.same(P"/", dir.normalize("/////")) | ||
68 | assert.are.same(P"/", dir.normalize("/a/b/.././../c/./../../")) | ||
69 | end) | ||
70 | end) | ||
71 | |||
72 | end) | ||
diff --git a/spec/unit/fetch_spec.lua b/spec/unit/fetch_spec.lua new file mode 100644 index 00000000..38da379e --- /dev/null +++ b/spec/unit/fetch_spec.lua | |||
@@ -0,0 +1,488 @@ | |||
1 | local test_env = require("spec.util.test_env") | ||
2 | |||
3 | test_env.unload_luarocks() | ||
4 | test_env.setup_specs() | ||
5 | local cfg = require("luarocks.core.cfg") | ||
6 | local fetch = require("luarocks.fetch") | ||
7 | local fs = require("luarocks.fs") | ||
8 | local dir = require("luarocks.dir") | ||
9 | local path = require("luarocks.path") | ||
10 | local rockspecs = require("luarocks.rockspecs") | ||
11 | local lfs = require("lfs") | ||
12 | local get_tmp_path = test_env.get_tmp_path | ||
13 | local testing_paths = test_env.testing_paths | ||
14 | local write_file = test_env.write_file | ||
15 | local P = test_env.P | ||
16 | |||
17 | describe("luarocks fetch #unit", function() | ||
18 | local are_same_files = function(file1, file2) | ||
19 | return file1 == file2 or lfs.attributes(file1).ino == lfs.attributes(file2).ino | ||
20 | end | ||
21 | |||
22 | local runner | ||
23 | |||
24 | setup(function() | ||
25 | cfg.init() | ||
26 | fs.init() | ||
27 | |||
28 | -- mock network access | ||
29 | fs.download = function(url, destfile) | ||
30 | local mockfile = P(url:gsub("http://localhost:8080/file", testing_paths.fixtures_dir)) | ||
31 | if not destfile then | ||
32 | destfile = dir.base_name(mockfile) | ||
33 | end | ||
34 | destfile = fs.absolute_name(destfile) | ||
35 | |||
36 | local fdr = io.open(mockfile, "rb") | ||
37 | if not fdr then | ||
38 | return nil, "mock failed opening for reading" | ||
39 | end | ||
40 | |||
41 | local fdw = io.open(destfile, "wb") | ||
42 | if not fdr then | ||
43 | return nil, "mock failed opening for writing" | ||
44 | end | ||
45 | |||
46 | local data = fdr:read("*a") | ||
47 | if not data then | ||
48 | return nil, "mock failed reading" | ||
49 | end | ||
50 | |||
51 | local ok = fdw:write(data) | ||
52 | if not ok then | ||
53 | return nil, "mock failed writing" | ||
54 | end | ||
55 | |||
56 | fdr:close() | ||
57 | fdw:close() | ||
58 | |||
59 | return true, destfile | ||
60 | end | ||
61 | |||
62 | runner = require("luacov.runner") | ||
63 | runner.init(testing_paths.testrun_dir .. "/luacov.config") | ||
64 | runner.tick = true | ||
65 | end) | ||
66 | |||
67 | teardown(function() | ||
68 | runner.shutdown() | ||
69 | end) | ||
70 | |||
71 | |||
72 | describe("fetch.fetch_url", function() | ||
73 | |||
74 | it("fetches the url argument and returns the absolute path of the fetched file", function() | ||
75 | test_env.run_in_tmp(function() | ||
76 | local fetchedfile, err = fetch.fetch_url("http://localhost:8080/file/a_rock.lua") | ||
77 | assert(fetchedfile, err) | ||
78 | assert.truthy(are_same_files(fetchedfile, lfs.currentdir() .. "/a_rock.lua")) | ||
79 | local fd = assert(io.open(fetchedfile, "r")) | ||
80 | local fetchedcontent = assert(fd:read("*a")) | ||
81 | fd:close() | ||
82 | fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) | ||
83 | local filecontent = assert(fd:read("*a")) | ||
84 | fd:close() | ||
85 | assert.same(fetchedcontent, filecontent) | ||
86 | end, finally) | ||
87 | end) | ||
88 | |||
89 | it("returns the absolute path of the filename argument if the url represents a file", function() | ||
90 | test_env.run_in_tmp(function() | ||
91 | write_file("test.lua", "return {}") | ||
92 | |||
93 | local file, err = fetch.fetch_url("file://test.lua") | ||
94 | assert.truthy(file, err) | ||
95 | assert.truthy(are_same_files(file, lfs.currentdir() .. "/test.lua")) | ||
96 | fs.pop_dir() | ||
97 | end, finally) | ||
98 | end) | ||
99 | |||
100 | it("fails if local path is invalid and returns a helpful hint for relative paths", function() | ||
101 | test_env.run_in_tmp(function() | ||
102 | local ok, err = fetch.fetch_url("file://boo.lua") | ||
103 | assert.falsy(ok) | ||
104 | assert.match("note that given path in rockspec is not absolute: file://boo.lua", err) | ||
105 | end, finally) | ||
106 | end) | ||
107 | |||
108 | it("returns false and does nothing if the url argument contains a nonexistent file", function() | ||
109 | assert.falsy(fetch.fetch_url("http://localhost:8080/file/nonexistent")) | ||
110 | end) | ||
111 | |||
112 | it("returns false and does nothing if the url argument is invalid", function() | ||
113 | assert.falsy(fetch.fetch_url("invalid://url", "file")) | ||
114 | end) | ||
115 | end) | ||
116 | |||
117 | describe("fetch.fetch_url_at_temp_dir", function() | ||
118 | |||
119 | it("returns the absolute path and the parent directory of the file specified by the url", function() | ||
120 | test_env.run_in_tmp(function(tmpdir) | ||
121 | local tmpfile = tmpdir .. "/tmpfile" | ||
122 | assert(io.open(tmpfile, "w")) | ||
123 | local pathname, dirname = fetch.fetch_url_at_temp_dir("file://" .. tmpfile, "test") | ||
124 | assert.truthy(are_same_files(tmpfile, pathname)) | ||
125 | assert.truthy(are_same_files(tmpdir, dirname)) | ||
126 | end, finally) | ||
127 | end) | ||
128 | |||
129 | it("returns true and fetches the url into a temporary dir", function() | ||
130 | test_env.run_in_tmp(function() | ||
131 | local fetchedfile, tmpdir = fetch.fetch_url_at_temp_dir("http://localhost:8080/file/a_rock.lua", "test") | ||
132 | assert(fetchedfile, tmpdir) | ||
133 | assert.truthy(are_same_files(fetchedfile, tmpdir .. "/a_rock.lua")) | ||
134 | local fd = assert(io.open(fetchedfile, "r")) | ||
135 | local fetchedcontent = assert(fd:read("*a")) | ||
136 | fd:close() | ||
137 | fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) | ||
138 | local filecontent = assert(fd:read("*a")) | ||
139 | fd:close() | ||
140 | assert.same(fetchedcontent, filecontent) | ||
141 | end, finally) | ||
142 | end) | ||
143 | |||
144 | it("returns true and fetches the url into a temporary dir with custom filename", function() | ||
145 | test_env.run_in_tmp(function() | ||
146 | local fetchedfile, tmpdir = fetch.fetch_url_at_temp_dir("http://localhost:8080/file/a_rock.lua", "test", "my_a_rock.lua") | ||
147 | assert(fetchedfile, tmpdir) | ||
148 | assert.truthy(are_same_files(fetchedfile, tmpdir .. "/my_a_rock.lua")) | ||
149 | assert.truthy(string.find(tmpdir, "test")) | ||
150 | local fd = assert(io.open(fetchedfile, "r")) | ||
151 | local fetchedcontent = assert(fd:read("*a")) | ||
152 | fd:close() | ||
153 | fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) | ||
154 | local filecontent = assert(fd:read("*a")) | ||
155 | fd:close() | ||
156 | assert.same(fetchedcontent, filecontent) | ||
157 | end, finally) | ||
158 | end) | ||
159 | |||
160 | it("returns false and does nothing if the file specified in the url is nonexistent", function() | ||
161 | assert.falsy(fetch.fetch_url_at_temp_dir("file://nonexistent", "test")) | ||
162 | assert.falsy(fetch.fetch_url_at_temp_dir("http://localhost:8080/file/nonexistent", "test")) | ||
163 | end) | ||
164 | |||
165 | it("returns false and does nothing if the url is invalid", function() | ||
166 | assert.falsy(fetch.fetch_url_at_temp_dir("url://invalid", "test")) | ||
167 | end) | ||
168 | end) | ||
169 | |||
170 | describe("fetch.find_base_dir", function() | ||
171 | it("extracts the archive given by the file argument and returns the inferred and the actual root directory in the archive", function() | ||
172 | test_env.run_in_tmp(function() | ||
173 | local url = "http://localhost:8080/file/an_upstream_tarball-0.1.tar.gz" | ||
174 | local file, tmpdir = assert(fetch.fetch_url_at_temp_dir(url, "test")) | ||
175 | local inferreddir, founddir = fetch.find_base_dir(file, tmpdir, url) | ||
176 | assert.truthy(are_same_files(inferreddir, founddir)) | ||
177 | assert.truthy(lfs.attributes(tmpdir .. "/" .. founddir)) | ||
178 | end, finally) | ||
179 | end) | ||
180 | |||
181 | it("extracts the archive given by the file argument with given base directory and returns the inferred and the actual root directory in the archive", function() | ||
182 | test_env.run_in_tmp(function() | ||
183 | local url = "http://localhost:8080/file/an_upstream_tarball-0.1.tar.gz" | ||
184 | local file, tmpdir = assert(fetch.fetch_url_at_temp_dir(url, "test")) | ||
185 | local inferreddir, founddir = fetch.find_base_dir(file, tmpdir, url, "basedir") | ||
186 | assert.truthy(are_same_files(inferreddir, "basedir")) | ||
187 | assert.truthy(are_same_files(founddir, "an_upstream_tarball-0.1")) | ||
188 | assert.truthy(lfs.attributes(tmpdir .. "/" .. founddir)) | ||
189 | end, finally) | ||
190 | end) | ||
191 | |||
192 | it("returns false and does nothing if the temporary directory doesn't exist", function() | ||
193 | assert.falsy(fetch.find_base_dir("file", "nonexistent", "url")) | ||
194 | end) | ||
195 | end) | ||
196 | |||
197 | describe("fetch.fetch_and_unpack_rock", function() | ||
198 | |||
199 | it("unpacks the rock file from the url and returns its resulting temporary parent directory", function() | ||
200 | test_env.run_in_tmp(function() | ||
201 | local tmpdir = fetch.fetch_and_unpack_rock("http://localhost:8080/file/a_rock-1.0-1.src.rock") | ||
202 | assert.truthy(string.find(tmpdir, "a_rock%-1%.0%-1")) | ||
203 | assert.truthy(lfs.attributes(tmpdir .. "/a_rock-1.0-1.rockspec")) | ||
204 | assert.truthy(lfs.attributes(tmpdir .. "/a_rock.lua")) | ||
205 | end, finally) | ||
206 | end) | ||
207 | |||
208 | it("unpacks the rock file from the url with custom unpacking directory", function() | ||
209 | test_env.run_in_tmp(function() | ||
210 | local tmpdir = get_tmp_path() | ||
211 | lfs.mkdir(tmpdir) | ||
212 | local resultingdir = fetch.fetch_and_unpack_rock("http://localhost:8080/file/a_rock-1.0-1.src.rock", tmpdir) | ||
213 | assert.truthy(are_same_files(resultingdir, tmpdir)) | ||
214 | assert.truthy(lfs.attributes(resultingdir .. "/a_rock-1.0-1.rockspec")) | ||
215 | assert.truthy(lfs.attributes(resultingdir .. "/a_rock.lua")) | ||
216 | end, finally) | ||
217 | end) | ||
218 | |||
219 | it("does nothing if the url doesn't represent a rock file", function() | ||
220 | assert.falsy(pcall(fetch.fetch_and_unpack_rock, "http://localhost:8080/file/a_rock.lua")) | ||
221 | end) | ||
222 | |||
223 | it("does nothing if the rock file url is invalid", function() | ||
224 | assert.falsy(pcall(fetch.fetch_and_unpack_rock, "url://invalid")) | ||
225 | end) | ||
226 | |||
227 | it("does nothing if the rock file url represents a nonexistent file", function() | ||
228 | assert.falsy(pcall(fetch.fetch_and_unpack_rock, "url://invalid")) | ||
229 | assert.falsy(pcall(fetch.fetch_and_unpack_rock, "http://localhost:8080/file/nonexistent")) | ||
230 | end) | ||
231 | end) | ||
232 | |||
233 | describe("fetch.load_local_rockspec", function() | ||
234 | it("returns a table representing the rockspec from the given file skipping some checks if the quick argument is enabled", function() | ||
235 | test_env.run_in_tmp(function() | ||
236 | local rockspec = fetch.load_local_rockspec(testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec", true) | ||
237 | assert.same(rockspec.name, "a_rock") | ||
238 | assert.same(rockspec.version, "1.0-1") | ||
239 | assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") | ||
240 | assert.same(rockspec.description, { summary = "An example rockspec" }) | ||
241 | |||
242 | write_file("missing_mandatory_field-1.0-1.rockspec", [[ | ||
243 | package="missing_mandatory_field" | ||
244 | version="1.0-1" | ||
245 | source = { | ||
246 | url = "http://example.com/foo.tar.gz" | ||
247 | } | ||
248 | ]]) | ||
249 | rockspec = fetch.load_local_rockspec("missing_mandatory_field-1.0-1.rockspec", true) | ||
250 | assert.same(rockspec.name, "missing_mandatory_field") | ||
251 | assert.same(rockspec.version, "1.0-1") | ||
252 | assert.same(rockspec.source.url, "http://example.com/foo.tar.gz") | ||
253 | |||
254 | write_file("unknown_field-1.0-1.rockspec", [[ | ||
255 | package="unknown_field" | ||
256 | version="1.0-1" | ||
257 | source = { | ||
258 | url = "http://example.com/foo.tar.gz" | ||
259 | } | ||
260 | unknown="foo" | ||
261 | ]]) | ||
262 | rockspec = fetch.load_local_rockspec("unknown_field-1.0-1.rockspec", true) | ||
263 | assert.same(rockspec.name, "unknown_field") | ||
264 | assert.same(rockspec.version, "1.0-1") | ||
265 | assert.same(rockspec.source.url, "http://example.com/foo.tar.gz") | ||
266 | |||
267 | -- The previous calls fail if the detailed checking is done | ||
268 | path.use_tree(testing_paths.testing_tree) | ||
269 | assert.falsy(fetch.load_local_rockspec("missing_mandatory_field-1.0-1.rockspec")) | ||
270 | assert.falsy(fetch.load_local_rockspec("unknown_field-1.0-1.rockspec")) | ||
271 | end, finally) | ||
272 | end) | ||
273 | |||
274 | it("returns a table representing the rockspec from the given file", function() | ||
275 | test_env.run_in_tmp(function() | ||
276 | path.use_tree(testing_paths.testing_tree) | ||
277 | local rockspec = fetch.load_local_rockspec(testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec") | ||
278 | assert.same(rockspec.name, "a_rock") | ||
279 | assert.same(rockspec.version, "1.0-1") | ||
280 | assert.same(rockspec.description, { summary = "An example rockspec" }) | ||
281 | assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") | ||
282 | end, finally) | ||
283 | end) | ||
284 | |||
285 | it("returns false if the rockspec in invalid", function() | ||
286 | assert.falsy(fetch.load_local_rockspec(testing_paths.fixtures_dir .. "/invalid_say-1.3-1.rockspec")) | ||
287 | end) | ||
288 | |||
289 | it("returns false if the rockspec version is not supported", function() | ||
290 | assert.falsy(fetch.load_local_rockspec("invalid_version.rockspec")) | ||
291 | end) | ||
292 | |||
293 | it("returns false if the rockspec doesn't pass the type checking", function() | ||
294 | test_env.run_in_tmp(function() | ||
295 | write_file("type_mismatch_string-1.0-1.rockspec", [[ | ||
296 | package="type_mismatch_version" | ||
297 | version=1.0 | ||
298 | ]]) | ||
299 | assert.falsy(fetch.load_local_rockspec("type_mismatch_string-1.0-1.rockspec")) | ||
300 | end, finally) | ||
301 | end) | ||
302 | |||
303 | it("returns false if the rockspec file name is not right", function() | ||
304 | test_env.run_in_tmp(function() | ||
305 | write_file("invalid_rockspec_name.rockspec", [[ | ||
306 | package="invalid_rockspec_name" | ||
307 | version="1.0-1" | ||
308 | source = { | ||
309 | url = "http://example.com/foo.tar.gz" | ||
310 | } | ||
311 | build = { | ||
312 | |||
313 | } | ||
314 | ]]) | ||
315 | assert.falsy(fetch.load_local_rockspec("invalid_rockspec_name.rockspec")) | ||
316 | end, finally) | ||
317 | end) | ||
318 | |||
319 | it("returns false if the version in the rockspec file name doesn't match the version declared in the rockspec", function() | ||
320 | test_env.run_in_tmp(function() | ||
321 | write_file("inconsistent_versions-1.0-1.rockspec", [[ | ||
322 | package="inconsistent_versions" | ||
323 | version="1.0-2" | ||
324 | source = { | ||
325 | url = "http://example.com/foo.tar.gz" | ||
326 | } | ||
327 | build = { | ||
328 | |||
329 | } | ||
330 | ]]) | ||
331 | assert.falsy(fetch.load_local_rockspec("inconsistent_versions-1.0-1.rockspec")) | ||
332 | end, finally) | ||
333 | end) | ||
334 | end) | ||
335 | |||
336 | describe("fetch.load_rockspec", function() | ||
337 | |||
338 | it("returns a table containing the requested rockspec by downloading it into a temporary directory", function() | ||
339 | test_env.run_in_tmp(function() | ||
340 | path.use_tree(testing_paths.testing_tree) | ||
341 | local rockspec = fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec") | ||
342 | assert.same(rockspec.name, "a_rock") | ||
343 | assert.same(rockspec.version, "1.0-1") | ||
344 | assert.same(rockspec.description, { summary = "An example rockspec" }) | ||
345 | assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") | ||
346 | rockspec = fetch.load_rockspec(testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec") | ||
347 | assert.same(rockspec.name, "a_rock") | ||
348 | assert.same(rockspec.version, "1.0-1") | ||
349 | assert.same(rockspec.description, { summary = "An example rockspec" }) | ||
350 | assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") | ||
351 | end, finally) | ||
352 | end) | ||
353 | |||
354 | it("returns a table containing the requested rockspec by downloading it into a given directory", function() | ||
355 | test_env.run_in_tmp(function() | ||
356 | local tmpdir = get_tmp_path() | ||
357 | lfs.mkdir(tmpdir) | ||
358 | |||
359 | path.use_tree(testing_paths.testing_tree) | ||
360 | local rockspec = fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec", tmpdir) | ||
361 | assert.same(rockspec.name, "a_rock") | ||
362 | assert.same(rockspec.version, "1.0-1") | ||
363 | assert.same(rockspec.description, { summary = "An example rockspec" }) | ||
364 | assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") | ||
365 | assert.truthy(lfs.attributes(tmpdir .. "/a_rock-1.0-1.rockspec")) | ||
366 | |||
367 | lfs.rmdir(tmpdir) | ||
368 | end, finally) | ||
369 | end) | ||
370 | |||
371 | it("returns false if the given download directory doesn't exist", function() | ||
372 | assert.falsy(fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec", "nonexistent")) | ||
373 | end) | ||
374 | |||
375 | it("returns false if the given filename is not a valid rockspec name", function() | ||
376 | assert.falsy(fetch.load_rockspec("http://localhost:8080/file/a_rock.lua")) | ||
377 | end) | ||
378 | end) | ||
379 | |||
380 | describe("fetch.get_sources", function() | ||
381 | |||
382 | it("downloads the sources for building a rock and returns the resulting source filename and its parent directory", function() | ||
383 | test_env.run_in_tmp(function() | ||
384 | local rockspec = assert(fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec")) | ||
385 | local file, dirname = fetch.get_sources(rockspec, false) | ||
386 | assert.truthy(are_same_files(dirname .. "/a_rock.lua", file)) | ||
387 | end, finally) | ||
388 | end) | ||
389 | |||
390 | it("downloads the sources for building a rock into a given directory and returns the resulting source filename and its parent directory", function() | ||
391 | test_env.run_in_tmp(function() | ||
392 | local tmpdir = get_tmp_path() | ||
393 | lfs.mkdir(tmpdir) | ||
394 | local rockspec = assert(fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec")) | ||
395 | local file, dirname = fetch.get_sources(rockspec, false, tmpdir) | ||
396 | assert.truthy(are_same_files(tmpdir, dirname)) | ||
397 | assert.truthy(are_same_files(dirname .. "/a_rock.lua", file)) | ||
398 | lfs.rmdir(tmpdir) | ||
399 | end, finally) | ||
400 | end) | ||
401 | |||
402 | it("downloads the sources for building a rock, extracts the downloaded tarball and returns the resulting source filename and its parent directory", function() | ||
403 | test_env.run_in_tmp(function() | ||
404 | local rockspec = assert(fetch.load_rockspec("http://localhost:8080/file/busted_project-0.1-1.rockspec")) | ||
405 | local file, dirname = fetch.get_sources(rockspec, true) | ||
406 | assert.truthy(are_same_files(dirname .. "/busted_project-0.1.tar.gz", file)) | ||
407 | assert.truthy(lfs.attributes(dirname .. "/busted_project")) | ||
408 | assert.truthy(lfs.attributes(dirname .. "/busted_project/sum.lua")) | ||
409 | assert.truthy(lfs.attributes(dirname .. "/busted_project/spec/sum_spec.lua")) | ||
410 | end, finally) | ||
411 | end) | ||
412 | |||
413 | it("returns false and does nothing if the destination directory doesn't exist", function() | ||
414 | test_env.run_in_tmp(function() | ||
415 | local rockspec = assert(fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec")) | ||
416 | assert.falsy(fetch.get_sources(rockspec, false, "nonexistent")) | ||
417 | end, finally) | ||
418 | end) | ||
419 | |||
420 | it("returns false and does nothing if the rockspec source url is invalid", function() | ||
421 | test_env.run_in_tmp(function(tmpdir) | ||
422 | write_file(tmpdir .. "/invalid_url-1.0-1.rockspec", [[ | ||
423 | package="invalid_url" | ||
424 | version="1.0-1" | ||
425 | source = { | ||
426 | url = "http://localhost:8080/file/nonexistent" | ||
427 | } | ||
428 | build = { | ||
429 | |||
430 | } | ||
431 | ]]) | ||
432 | local rockspec = assert(fetch.load_rockspec(tmpdir .. "/invalid_url-1.0-1.rockspec")) | ||
433 | assert.falsy(fetch.get_sources(rockspec, false)) | ||
434 | end, finally) | ||
435 | end) | ||
436 | |||
437 | it("returns false and does nothing if the downloaded rockspec has an invalid md5 checksum", function() | ||
438 | test_env.run_in_tmp(function() | ||
439 | write_file("invalid_checksum-1.0-1.rockspec", [[ | ||
440 | package="invalid_checksum" | ||
441 | version="1.0-1" | ||
442 | source = { | ||
443 | url = "http://localhost:8080/file/a_rock.lua", | ||
444 | md5 = "invalid" | ||
445 | } | ||
446 | build = { | ||
447 | |||
448 | } | ||
449 | ]]) | ||
450 | local rockspec = assert(fetch.load_rockspec("invalid_checksum-1.0-1.rockspec")) | ||
451 | assert.falsy(fetch.get_sources(rockspec, false)) | ||
452 | end, finally) | ||
453 | end) | ||
454 | end) | ||
455 | |||
456 | describe("fetch_sources #unix #git", function() | ||
457 | local git_repo = require("spec.util.git_repo") | ||
458 | |||
459 | local git | ||
460 | |||
461 | setup(function() | ||
462 | git = git_repo.start() | ||
463 | end) | ||
464 | |||
465 | teardown(function() | ||
466 | if git then | ||
467 | git:stop() | ||
468 | end | ||
469 | end) | ||
470 | |||
471 | it("from #git", function() | ||
472 | local rockspec, err = rockspecs.from_persisted_table("testrock-dev-1.rockspec", { | ||
473 | rockspec_format = "3.0", | ||
474 | package = "testrock", | ||
475 | version = "dev-1", | ||
476 | source = { | ||
477 | url = "git://localhost/testrock", | ||
478 | }, | ||
479 | }, nil) | ||
480 | assert.falsy(err) | ||
481 | local pathname, tmpdir = fetch.fetch_sources(rockspec, false) | ||
482 | assert.are.same("testrock", pathname) | ||
483 | assert.match("luarocks_testrock%-dev%-1%-", tmpdir) | ||
484 | assert.match("^%d%d%d%d%d%d%d%d.%d%d%d%d%d%d.%x+$", tostring(rockspec.source.identifier)) | ||
485 | end) | ||
486 | end) | ||
487 | |||
488 | end) | ||
diff --git a/spec/unit/fs_spec.lua b/spec/unit/fs_spec.lua new file mode 100644 index 00000000..aea86af3 --- /dev/null +++ b/spec/unit/fs_spec.lua | |||
@@ -0,0 +1,1607 @@ | |||
1 | local test_env = require("spec.util.test_env") | ||
2 | |||
3 | test_env.unload_luarocks() | ||
4 | test_env.setup_specs() | ||
5 | local fs = require("luarocks.fs") | ||
6 | local path = require("luarocks.path") | ||
7 | local cfg = require("luarocks.core.cfg") | ||
8 | local lfs = require("lfs") | ||
9 | local is_win = test_env.TEST_TARGET_OS == "windows" | ||
10 | local posix_ok = pcall(require, "posix") | ||
11 | local testing_paths = test_env.testing_paths | ||
12 | local get_tmp_path = test_env.get_tmp_path | ||
13 | local write_file = test_env.write_file | ||
14 | local P = test_env.P | ||
15 | |||
16 | -- A chdir that works in both full and minimal mode, setting | ||
17 | -- both the real process current dir and the LuaRocks internal stack in minimal mode | ||
18 | local function chdir(d) | ||
19 | lfs.chdir(d) | ||
20 | fs.change_dir(d) | ||
21 | end | ||
22 | |||
23 | describe("luarocks.fs #unit", function() | ||
24 | local exists_file = function(path) | ||
25 | local ok, err, code = os.rename(path, path) | ||
26 | if not ok and code == 13 then | ||
27 | return true | ||
28 | end | ||
29 | return ok | ||
30 | end | ||
31 | |||
32 | local create_file = function(path, content) | ||
33 | local fd = assert(io.open(path, "w")) | ||
34 | if not content then | ||
35 | content = "foo" | ||
36 | end | ||
37 | assert(fd:write(content)) | ||
38 | fd:close() | ||
39 | end | ||
40 | |||
41 | local make_unreadable = function(path) | ||
42 | if is_win then | ||
43 | fs.execute("icacls " .. fs.Q(path) .. " /inheritance:d /deny \"%USERNAME%\":(R)") | ||
44 | else | ||
45 | fs.execute("chmod -r " .. fs.Q(path)) | ||
46 | end | ||
47 | end | ||
48 | |||
49 | local make_unwritable = function(path) | ||
50 | if is_win then | ||
51 | fs.execute("icacls " .. fs.Q(path) .. " /inheritance:d /deny \"%USERNAME%\":(W,M)") | ||
52 | else | ||
53 | fs.execute("chmod -w " .. fs.Q(path)) | ||
54 | end | ||
55 | end | ||
56 | |||
57 | local make_unexecutable = function(path) | ||
58 | if is_win then | ||
59 | fs.execute("icacls " .. fs.Q(path) .. " /inheritance:d /deny \"%USERNAME%\":(X)") | ||
60 | else | ||
61 | fs.execute("chmod -x " .. fs.Q(path)) | ||
62 | end | ||
63 | end | ||
64 | |||
65 | local runner | ||
66 | |||
67 | setup(function() | ||
68 | cfg.init() | ||
69 | fs.init() | ||
70 | runner = require("luacov.runner") | ||
71 | runner.init(testing_paths.testrun_dir .. "/luacov.config") | ||
72 | runner.tick = true | ||
73 | end) | ||
74 | |||
75 | teardown(function() | ||
76 | runner.shutdown() | ||
77 | end) | ||
78 | |||
79 | describe("fs.Q", function() | ||
80 | it("simple argument", function() | ||
81 | assert.are.same(is_win and '"foo"' or "'foo'", fs.Q("foo")) | ||
82 | end) | ||
83 | |||
84 | it("argument with quotes", function() | ||
85 | assert.are.same(is_win and [["it's \"quoting\""]] or [['it'\''s "quoting"']], fs.Q([[it's "quoting"]])) | ||
86 | end) | ||
87 | |||
88 | it("argument with special characters", function() | ||
89 | assert.are.same(is_win and [["\\"%" \\\\" \\\\\\"]] or [['\% \\" \\\']], fs.Q([[\% \\" \\\]])) | ||
90 | end) | ||
91 | end) | ||
92 | |||
93 | describe("fs.absolute_name", function() | ||
94 | it("unchanged if already absolute", function() | ||
95 | if is_win then | ||
96 | assert.are.same(P"c:\\foo\\bar", fs.absolute_name("\"c:\\foo\\bar\"")) | ||
97 | assert.are.same(P"c:\\foo\\bar", fs.absolute_name("c:\\foo\\bar")) | ||
98 | assert.are.same(P"d:\\foo\\bar", fs.absolute_name("d:\\foo\\bar")) | ||
99 | assert.are.same(P"\\foo\\bar", fs.absolute_name("\\foo\\bar")) | ||
100 | else | ||
101 | assert.are.same(P"/foo/bar", fs.absolute_name("/foo/bar")) | ||
102 | end | ||
103 | end) | ||
104 | |||
105 | it("converts to absolute if relative", function() | ||
106 | local cur = fs.current_dir() | ||
107 | if is_win then | ||
108 | assert.are.same(P(cur .. "/foo\\bar"), fs.absolute_name("\"foo\\bar\"")) | ||
109 | assert.are.same(P(cur .. "/foo\\bar"), fs.absolute_name("foo\\bar")) | ||
110 | else | ||
111 | assert.are.same(P(cur .. "/foo/bar"), fs.absolute_name("foo/bar")) | ||
112 | end | ||
113 | end) | ||
114 | |||
115 | it("converts a relative to specified base if given", function() | ||
116 | if is_win then | ||
117 | assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("\"foo\\bar\"", "c:\\bla")) | ||
118 | assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("foo/bar", "c:\\bla")) | ||
119 | assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("foo\\bar", "c:\\bla\\")) | ||
120 | else | ||
121 | assert.are.same(P"/bla/foo/bar", fs.absolute_name("foo/bar", "/bla")) | ||
122 | assert.are.same(P"/bla/foo/bar", fs.absolute_name("foo/bar", "/bla/")) | ||
123 | end | ||
124 | end) | ||
125 | end) | ||
126 | |||
127 | describe("fs.execute_string", function() | ||
128 | local tmpdir | ||
129 | |||
130 | after_each(function() | ||
131 | if tmpdir then | ||
132 | lfs.rmdir(tmpdir) | ||
133 | tmpdir = nil | ||
134 | end | ||
135 | end) | ||
136 | |||
137 | it("returns the status code and runs the command given in the argument", function() | ||
138 | tmpdir = get_tmp_path() | ||
139 | assert.truthy(fs.execute_string("mkdir " .. fs.Q(tmpdir))) | ||
140 | assert.truthy(fs.is_dir(tmpdir)) | ||
141 | assert.falsy(fs.execute_string("invalidcommand")) | ||
142 | end) | ||
143 | end) | ||
144 | |||
145 | describe("fs.dir_iterator", function() | ||
146 | local tmpfile1 | ||
147 | local tmpfile2 | ||
148 | local tmpdir | ||
149 | local intdir | ||
150 | |||
151 | after_each(function() | ||
152 | if tmpfile1 then | ||
153 | os.remove(tmpfile1) | ||
154 | tmpfile1 = nil | ||
155 | end | ||
156 | if tmpfile2 then | ||
157 | os.remove(tmpfile2) | ||
158 | tmpfile2 = nil | ||
159 | end | ||
160 | if intdir then | ||
161 | lfs.rmdir(intdir) | ||
162 | intdir = nil | ||
163 | end | ||
164 | if tmpdir then | ||
165 | lfs.rmdir(tmpdir) | ||
166 | tmpdir = nil | ||
167 | end | ||
168 | end) | ||
169 | |||
170 | it("yields all files and directories in the directory given as argument during the iterations", function() | ||
171 | tmpdir = get_tmp_path() | ||
172 | lfs.mkdir(tmpdir) | ||
173 | tmpfile1 = tmpdir .. "/file1" | ||
174 | create_file(tmpfile1) | ||
175 | tmpfile2 = tmpdir .. "/file2" | ||
176 | create_file(tmpfile2) | ||
177 | intdir = tmpdir .. "/intdir" | ||
178 | lfs.mkdir(intdir) | ||
179 | local dirTable = {} | ||
180 | local dirCount = 0 | ||
181 | local crt = coroutine.create(fs.dir_iterator) | ||
182 | while coroutine.status(crt) ~= "dead" do | ||
183 | local ok, val = coroutine.resume(crt, tmpdir) | ||
184 | if ok and val ~= nil then | ||
185 | dirTable[val] = true | ||
186 | dirCount = dirCount + 1 | ||
187 | end | ||
188 | end | ||
189 | assert.same(dirCount, 3) | ||
190 | assert.is_not.same(dirTable["file1"], nil) | ||
191 | assert.is_not.same(dirTable["file2"], nil) | ||
192 | assert.is_not.same(dirTable["intdir"], nil) | ||
193 | dirCount = 0 | ||
194 | crt = coroutine.create(fs.dir_iterator) | ||
195 | while coroutine.status(crt) ~= "dead" do | ||
196 | local ok, val = coroutine.resume(crt, intdir) | ||
197 | if ok and val ~= nil then | ||
198 | dirCount = dirCount + 1 | ||
199 | end | ||
200 | end | ||
201 | assert.same(dirCount, 0) | ||
202 | end) | ||
203 | |||
204 | it("does nothing if the argument is a file", function() | ||
205 | tmpfile1 = get_tmp_path() | ||
206 | create_file(tmpfile1) | ||
207 | local crt = coroutine.create(fs.dir_iterator) | ||
208 | while coroutine.status(crt) ~= "dead" do | ||
209 | local ok, val = coroutine.resume(crt, tmpfile1) | ||
210 | assert.falsy(ok and res) | ||
211 | end | ||
212 | end) | ||
213 | |||
214 | it("does nothing if the argument is invalid", function() | ||
215 | local crt = coroutine.create(fs.dir_iterator) | ||
216 | while coroutine.status(crt) ~= "dead" do | ||
217 | local ok, val = coroutine.resume(crt, "/nonexistent") | ||
218 | assert.falsy(ok and res) | ||
219 | end | ||
220 | end) | ||
221 | end) | ||
222 | |||
223 | describe("fs.is_writable", function() | ||
224 | local tmpfile | ||
225 | local tmpdir | ||
226 | |||
227 | after_each(function() | ||
228 | if tmpfile then | ||
229 | os.remove(tmpfile) | ||
230 | tmpfile = nil | ||
231 | end | ||
232 | if tmpdir then | ||
233 | lfs.rmdir(tmpdir) | ||
234 | tmpdir = nil | ||
235 | end | ||
236 | end) | ||
237 | |||
238 | it("returns true if the file given as argument is writable", function() | ||
239 | tmpfile = get_tmp_path() | ||
240 | create_file(tmpfile) | ||
241 | assert.truthy(fs.is_writable(tmpfile)) | ||
242 | end) | ||
243 | |||
244 | it("returns true if the directory given as argument is writable", function() | ||
245 | tmpdir = get_tmp_path() | ||
246 | lfs.mkdir(tmpdir) | ||
247 | assert.truthy(fs.is_writable(tmpdir)) | ||
248 | tmpfile = tmpdir .. "/internalfile" | ||
249 | create_file(tmpfile) | ||
250 | make_unwritable(tmpfile) | ||
251 | assert.truthy(fs.is_writable(tmpdir)) | ||
252 | end) | ||
253 | |||
254 | it("returns false if the file given as argument is not writable", function() | ||
255 | tmpfile = get_tmp_path() | ||
256 | create_file(tmpfile) | ||
257 | make_unwritable(tmpfile) | ||
258 | assert.falsy(fs.is_writable(tmpfile)) | ||
259 | end) | ||
260 | |||
261 | it("returns false if the directory given as argument is not writable", function() | ||
262 | tmpdir = get_tmp_path() | ||
263 | lfs.mkdir(tmpdir) | ||
264 | make_unwritable(tmpdir) | ||
265 | assert.falsy(fs.is_writable(tmpdir)) | ||
266 | end) | ||
267 | |||
268 | it("returns false if the file or directory given as argument does not exist", function() | ||
269 | assert.falsy(fs.is_writable("/nonexistent")) | ||
270 | end) | ||
271 | end) | ||
272 | |||
273 | describe("fs.set_time #unix", function() | ||
274 | local tmpfile | ||
275 | local tmpdir | ||
276 | local intdir | ||
277 | |||
278 | after_each(function() | ||
279 | if tmpfile then | ||
280 | os.remove(tmpfile) | ||
281 | tmpfile = nil | ||
282 | end | ||
283 | if intdir then | ||
284 | os.remove(intdir) | ||
285 | intdir = nil | ||
286 | end | ||
287 | if tmpdir then | ||
288 | lfs.rmdir(tmpdir) | ||
289 | tmpdir = nil | ||
290 | end | ||
291 | end) | ||
292 | |||
293 | it("returns true and modifies the access time of the file given as argument", function() | ||
294 | tmpfile = get_tmp_path() | ||
295 | create_file(tmpfile) | ||
296 | local newtime = os.time() - 100 | ||
297 | assert.truthy(fs.set_time(tmpfile, newtime)) | ||
298 | assert.same(lfs.attributes(tmpfile, "access"), newtime) | ||
299 | assert.same(lfs.attributes(tmpfile, "modification"), newtime) | ||
300 | end) | ||
301 | |||
302 | it("returns true and modifies the access time of the directory given as argument", function() | ||
303 | tmpdir = get_tmp_path() | ||
304 | lfs.mkdir(tmpdir) | ||
305 | tmpfile = tmpdir .. "/internalfile" | ||
306 | create_file(tmpfile) | ||
307 | local newtime = os.time() - 100 | ||
308 | assert.truthy(fs.set_time(tmpdir, newtime)) | ||
309 | assert.same(lfs.attributes(tmpdir, "access"), newtime) | ||
310 | assert.same(lfs.attributes(tmpdir, "modification"), newtime) | ||
311 | assert.is_not.same(lfs.attributes(tmpfile, "access"), newtime) | ||
312 | assert.is_not.same(lfs.attributes(tmpfile, "modification"), newtime) | ||
313 | end) | ||
314 | |||
315 | it("returns false and does nothing if the file or directory given as arguments doesn't exist", function() | ||
316 | assert.falsy(fs.set_time("/nonexistent")) | ||
317 | end) | ||
318 | end) | ||
319 | |||
320 | describe("fs.set_permissions", function() | ||
321 | local readfile | ||
322 | local execfile | ||
323 | local tmpdir | ||
324 | |||
325 | after_each(function() | ||
326 | if readfile then | ||
327 | os.remove(readfile) | ||
328 | readfile = nil | ||
329 | end | ||
330 | if execfile then | ||
331 | os.remove(execfile) | ||
332 | execfile = nil | ||
333 | end | ||
334 | if tmpdir then | ||
335 | lfs.rmdir(tmpdir) | ||
336 | tmpdir = nil | ||
337 | end | ||
338 | end) | ||
339 | |||
340 | it("returns true and sets the permissions of the argument accordingly", function() | ||
341 | readfile = get_tmp_path() | ||
342 | create_file(readfile) | ||
343 | make_unreadable(readfile) | ||
344 | assert.falsy(io.open(readfile, "r")) | ||
345 | assert.truthy(fs.set_permissions(readfile, "read", "user")) | ||
346 | assert.truthy(io.open(readfile, "r")) | ||
347 | |||
348 | if is_win then | ||
349 | execfile = get_tmp_path() .. ".exe" | ||
350 | create_file(execfile) | ||
351 | else | ||
352 | execfile = get_tmp_path() .. ".sh" | ||
353 | create_file(execfile, "#!/bin/bash") | ||
354 | end | ||
355 | make_unexecutable(execfile) | ||
356 | local fd = assert(io.popen(execfile .. " 2>&1")) | ||
357 | local result = assert(fd:read("*a")) | ||
358 | assert.truthy(result:match("denied")) | ||
359 | fd:close() | ||
360 | assert.truthy(fs.set_permissions(execfile, "exec", "user")) | ||
361 | fd = assert(io.popen(execfile .. " 2>&1")) | ||
362 | result = assert(fd:read("*a")) | ||
363 | assert.falsy(result:match("denied")) | ||
364 | fd:close() | ||
365 | |||
366 | tmpdir = get_tmp_path() | ||
367 | lfs.mkdir(tmpdir) | ||
368 | make_unexecutable(tmpdir) | ||
369 | fd = assert(io.popen("cd " .. fs.Q(tmpdir) .. " 2>&1")) | ||
370 | result = assert(fd:read("*a")) | ||
371 | assert.truthy(result:match("denied") or result:match("can't cd")) | ||
372 | fd:close() | ||
373 | assert.truthy(fs.set_permissions(tmpdir, "exec", "user")) | ||
374 | fd = assert(io.popen("cd " .. fs.Q(tmpdir) .. " 2>&1")) | ||
375 | result = assert(fd:read("*a")) | ||
376 | assert.falsy(result:match("denied") or result:match("can't cd")) | ||
377 | fd:close() | ||
378 | end) | ||
379 | |||
380 | it("returns false and does nothing if the argument is nonexistent", function() | ||
381 | assert.falsy(fs.set_permissions("/nonexistent", "read", "user")) | ||
382 | end) | ||
383 | end) | ||
384 | |||
385 | describe("fs.is_file", function() | ||
386 | local tmpfile | ||
387 | local tmpdir | ||
388 | |||
389 | after_each(function() | ||
390 | if tmpfile then | ||
391 | os.remove(tmpfile) | ||
392 | tmpfile = nil | ||
393 | end | ||
394 | if tmpdir then | ||
395 | lfs.rmdir(tmpdir) | ||
396 | tmpdir = nil | ||
397 | end | ||
398 | end) | ||
399 | |||
400 | it("returns true when the argument is a file", function() | ||
401 | tmpfile = get_tmp_path() | ||
402 | create_file(tmpfile) | ||
403 | assert.same(true, fs.is_file(tmpfile)) | ||
404 | end) | ||
405 | |||
406 | it("returns false when the argument does not exist", function() | ||
407 | assert.same(false, fs.is_file("/nonexistent")) | ||
408 | end) | ||
409 | |||
410 | it("returns false when the argument exists but is not a file", function() | ||
411 | tmpdir = get_tmp_path() | ||
412 | lfs.mkdir(tmpdir) | ||
413 | assert.same(false, fs.is_file("/nonexistent")) | ||
414 | end) | ||
415 | |||
416 | it("#unix returns false when the argument is a symlink to a directory", function() | ||
417 | tmpdir = get_tmp_path() | ||
418 | lfs.mkdir(tmpdir) | ||
419 | local linkname = tmpdir .. "/symlink" | ||
420 | finally(function() os.remove(linkname) end) | ||
421 | lfs.link(tmpdir, linkname, true) | ||
422 | assert.falsy(fs.is_file(linkname)) | ||
423 | end) | ||
424 | |||
425 | it("#unix returns true when the argument is a symlink to a file", function() | ||
426 | tmpfile = get_tmp_path() | ||
427 | create_file(tmpfile) | ||
428 | local linkname = tmpfile .. "_symlink" | ||
429 | finally(function() os.remove(linkname) end) | ||
430 | lfs.link(tmpfile, linkname, true) | ||
431 | assert.truthy(fs.is_file(linkname)) | ||
432 | end) | ||
433 | end) | ||
434 | |||
435 | describe("fs.is_dir", function() | ||
436 | local tmpfile | ||
437 | local tmpdir | ||
438 | |||
439 | after_each(function() | ||
440 | if tmpfile then | ||
441 | os.remove(tmpfile) | ||
442 | tmpfile = nil | ||
443 | end | ||
444 | if tmpdir then | ||
445 | lfs.rmdir(tmpdir) | ||
446 | tmpdir = nil | ||
447 | end | ||
448 | end) | ||
449 | |||
450 | it("returns true when the argument is a directory", function() | ||
451 | tmpdir = get_tmp_path() | ||
452 | lfs.mkdir(tmpdir) | ||
453 | assert.truthy(fs.is_dir(tmpdir)) | ||
454 | end) | ||
455 | |||
456 | it("returns false when the argument is a file", function() | ||
457 | tmpfile = get_tmp_path() | ||
458 | create_file(tmpfile) | ||
459 | assert.falsy(fs.is_dir(tmpfile)) | ||
460 | end) | ||
461 | |||
462 | it("#unix returns true when the argument is a symlink to a directory", function() | ||
463 | tmpdir = get_tmp_path() | ||
464 | lfs.mkdir(tmpdir) | ||
465 | local linkname = tmpdir .. "/symlink" | ||
466 | finally(function() os.remove(linkname) end) | ||
467 | lfs.link(tmpdir, linkname, true) | ||
468 | assert.truthy(fs.is_dir(linkname)) | ||
469 | end) | ||
470 | |||
471 | it("#unix returns false when the argument is a symlink to a file", function() | ||
472 | tmpfile = get_tmp_path() | ||
473 | create_file(tmpfile) | ||
474 | local linkname = tmpfile .. "_symlink" | ||
475 | finally(function() os.remove(linkname) end) | ||
476 | lfs.link(tmpfile, linkname, true) | ||
477 | assert.falsy(fs.is_dir(linkname)) | ||
478 | end) | ||
479 | |||
480 | it("returns false when the argument does not exist", function() | ||
481 | assert.falsy(fs.is_dir("/nonexistent")) | ||
482 | end) | ||
483 | end) | ||
484 | |||
485 | describe("fs.exists", function() | ||
486 | local tmpfile | ||
487 | local tmpdir | ||
488 | |||
489 | after_each(function() | ||
490 | if tmpfile then | ||
491 | os.remove(tmpfile) | ||
492 | tmpfile = nil | ||
493 | end | ||
494 | if tmpdir then | ||
495 | lfs.rmdir(tmpdir) | ||
496 | tmpdir = nil | ||
497 | end | ||
498 | end) | ||
499 | |||
500 | it("returns true when the argument is a file", function() | ||
501 | tmpfile = get_tmp_path() | ||
502 | create_file(tmpfile) | ||
503 | assert.truthy(fs.exists(tmpfile)) | ||
504 | end) | ||
505 | |||
506 | it("returns true when the argument is a directory", function() | ||
507 | tmpdir = get_tmp_path() | ||
508 | lfs.mkdir(tmpdir) | ||
509 | assert.truthy(fs.exists(tmpdir)) | ||
510 | end) | ||
511 | |||
512 | it("returns false when the argument does not exist", function() | ||
513 | assert.falsy(fs.exists("/nonexistent")) | ||
514 | end) | ||
515 | end) | ||
516 | |||
517 | describe("fs.current_dir", function() | ||
518 | local tmpdir | ||
519 | local olddir | ||
520 | |||
521 | before_each(function() | ||
522 | olddir = lfs.currentdir() | ||
523 | end) | ||
524 | |||
525 | after_each(function() | ||
526 | if tmpdir then | ||
527 | lfs.rmdir(tmpdir) | ||
528 | tmpdir = nil | ||
529 | end | ||
530 | if olddir then | ||
531 | chdir(olddir) | ||
532 | olddir = nil | ||
533 | end | ||
534 | end) | ||
535 | |||
536 | it("returns the current working directory", function() | ||
537 | local currentdir = lfs.currentdir() | ||
538 | assert.same(currentdir, fs.current_dir()) | ||
539 | tmpdir = get_tmp_path() | ||
540 | lfs.mkdir(tmpdir) | ||
541 | assert.truthy(fs.change_dir(tmpdir)) | ||
542 | if is_win then | ||
543 | assert.same(tmpdir, fs.current_dir()) | ||
544 | else | ||
545 | assert.same(lfs.attributes(tmpdir).ino, lfs.attributes(fs.current_dir()).ino) | ||
546 | end | ||
547 | end) | ||
548 | end) | ||
549 | |||
550 | describe("fs.change_dir", function() | ||
551 | local tmpfile | ||
552 | local tmpdir | ||
553 | local olddir | ||
554 | |||
555 | before_each(function() | ||
556 | olddir = lfs.currentdir() | ||
557 | end) | ||
558 | |||
559 | after_each(function() | ||
560 | if tmpfile then | ||
561 | os.remove(tmpfile) | ||
562 | tmpfile = nil | ||
563 | end | ||
564 | if tmpdir then | ||
565 | lfs.rmdir(tmpdir) | ||
566 | tmpdir = nil | ||
567 | end | ||
568 | if olddir then | ||
569 | chdir(olddir) | ||
570 | olddir = nil | ||
571 | end | ||
572 | end) | ||
573 | |||
574 | it("returns true and changes the current working directory if the argument is a directory", function() | ||
575 | tmpdir = get_tmp_path() | ||
576 | lfs.mkdir(tmpdir) | ||
577 | assert.truthy(fs.change_dir(tmpdir)) | ||
578 | if is_win then | ||
579 | assert.same(tmpdir, fs.current_dir()) | ||
580 | else | ||
581 | assert.same(lfs.attributes(tmpdir).ino, lfs.attributes(lfs.currentdir()).ino) | ||
582 | end | ||
583 | end) | ||
584 | |||
585 | it("returns false and does nothing when the argument is a file", function() | ||
586 | tmpfile = get_tmp_path() | ||
587 | create_file(tmpfile) | ||
588 | assert.falsy(fs.change_dir(tmpfile)) | ||
589 | assert.same(olddir, lfs.currentdir()) | ||
590 | end) | ||
591 | |||
592 | it("returns false and does nothing when the argument does not exist", function() | ||
593 | assert.falsy(fs.change_dir("/nonexistent")) | ||
594 | assert.same(olddir, lfs.currentdir()) | ||
595 | end) | ||
596 | end) | ||
597 | |||
598 | describe("fs.change_dir_to_root", function() | ||
599 | local tmpdir | ||
600 | local olddir | ||
601 | |||
602 | before_each(function() | ||
603 | olddir = lfs.currentdir() | ||
604 | end) | ||
605 | |||
606 | after_each(function() | ||
607 | if tmpdir then | ||
608 | lfs.rmdir(tmpdir) | ||
609 | tmpdir = nil | ||
610 | end | ||
611 | if olddir then | ||
612 | chdir(olddir) | ||
613 | end | ||
614 | end) | ||
615 | |||
616 | it("returns true and changes the current directory to root if the current directory is valid", function() | ||
617 | tmpdir = get_tmp_path() | ||
618 | lfs.mkdir(tmpdir) | ||
619 | assert.truthy(fs.change_dir(tmpdir)) | ||
620 | assert.truthy(fs.change_dir_to_root()) | ||
621 | if is_win then | ||
622 | local curr_dir = fs.current_dir() | ||
623 | assert.truthy(curr_dir == "C:\\" or curr_dir == P"/") | ||
624 | else | ||
625 | assert.same(P"/", fs.current_dir()) | ||
626 | end | ||
627 | end) | ||
628 | |||
629 | it("returns false and does nothing if the current directory is not valid #unix", function() | ||
630 | tmpdir = get_tmp_path() | ||
631 | lfs.mkdir(tmpdir) | ||
632 | chdir(tmpdir) | ||
633 | lfs.rmdir(tmpdir) | ||
634 | assert.falsy(fs.change_dir_to_root()) | ||
635 | assert.is_not.same("/", lfs.currentdir()) | ||
636 | end) | ||
637 | end) | ||
638 | |||
639 | describe("fs.pop_dir", function() | ||
640 | local tmpdir | ||
641 | local olddir | ||
642 | |||
643 | before_each(function() | ||
644 | olddir = lfs.currentdir() | ||
645 | end) | ||
646 | |||
647 | after_each(function() | ||
648 | if tmpdir then | ||
649 | lfs.rmdir(tmpdir) | ||
650 | tmpdir = nil | ||
651 | end | ||
652 | if olddir then | ||
653 | chdir(olddir) | ||
654 | end | ||
655 | end) | ||
656 | |||
657 | it("returns true and changes the current directory to the previous one in the dir stack if the dir stack is not empty", function() | ||
658 | tmpdir = get_tmp_path() | ||
659 | lfs.mkdir(tmpdir) | ||
660 | assert.truthy(fs.change_dir(tmpdir)) | ||
661 | assert.truthy(fs.pop_dir()) | ||
662 | assert.same(olddir, lfs.currentdir()) | ||
663 | end) | ||
664 | end) | ||
665 | |||
666 | describe("fs.make_dir", function() | ||
667 | local tmpfile | ||
668 | local tmpdir | ||
669 | local intdir | ||
670 | |||
671 | after_each(function() | ||
672 | if tmpfile then | ||
673 | os.remove(tmpfile) | ||
674 | tmpfile = nil | ||
675 | end | ||
676 | if intdir then | ||
677 | lfs.rmdir(intdir) | ||
678 | intdir = nil | ||
679 | end | ||
680 | if tmpdir then | ||
681 | lfs.rmdir(tmpdir) | ||
682 | tmpdir = nil | ||
683 | end | ||
684 | end) | ||
685 | |||
686 | it("returns true and creates the directory specified by the argument", function() | ||
687 | tmpdir = get_tmp_path() | ||
688 | assert.truthy(fs.make_dir(tmpdir)) | ||
689 | assert.same("directory", lfs.attributes(tmpdir, "mode")) | ||
690 | end) | ||
691 | |||
692 | it("returns true and creates the directory path specified by the argument", function() | ||
693 | tmpdir = get_tmp_path() | ||
694 | intdir = "/internaldir" | ||
695 | local dirpath = tmpdir .. intdir | ||
696 | assert.truthy(fs.make_dir(dirpath)) | ||
697 | assert.same("directory", lfs.attributes(tmpdir, "mode")) | ||
698 | assert.same("directory", lfs.attributes(dirpath, "mode")) | ||
699 | end) | ||
700 | |||
701 | it("returns false and does nothing if the argument is not valid (file in the path)", function() | ||
702 | tmpfile = get_tmp_path() | ||
703 | local fd = assert(io.open(tmpfile, "w")) | ||
704 | assert(fd:write("foo")) | ||
705 | fd:close() | ||
706 | intdir = "/internaldir" | ||
707 | local dirpath = tmpfile .. intdir | ||
708 | assert.falsy(fs.make_dir(dirpath)) | ||
709 | end) | ||
710 | |||
711 | it("returns false and does nothing if the argument already exists", function() | ||
712 | tmpfile = get_tmp_path() | ||
713 | create_file(tmpfile) | ||
714 | assert.falsy(fs.make_dir(tmpfile)) | ||
715 | end) | ||
716 | end) | ||
717 | |||
718 | describe("fs.remove_dir_if_empty", function() | ||
719 | local tmpfile | ||
720 | local tmpdir | ||
721 | |||
722 | after_each(function() | ||
723 | if tmpfile then | ||
724 | os.remove(tmpfile) | ||
725 | tmpfile = nil | ||
726 | end | ||
727 | if tmpdir then | ||
728 | lfs.rmdir(tmpdir) | ||
729 | tmpdir = nil | ||
730 | end | ||
731 | end) | ||
732 | |||
733 | it("removes the directory specified by the argument if it is empty", function() | ||
734 | tmpdir = get_tmp_path() | ||
735 | lfs.mkdir(tmpdir) | ||
736 | fs.remove_dir_if_empty(tmpdir) | ||
737 | assert.falsy(exists_file(tmpdir)) | ||
738 | end) | ||
739 | |||
740 | it("does nothing if the directory specified by the argument is not empty", function() | ||
741 | tmpdir = get_tmp_path() | ||
742 | lfs.mkdir(tmpdir) | ||
743 | tmpfile = "/internalfile" | ||
744 | local filepath = tmpdir .. tmpfile | ||
745 | create_file(filepath) | ||
746 | fs.remove_dir_if_empty(tmpdir) | ||
747 | assert.truthy(exists_file(tmpdir)) | ||
748 | end) | ||
749 | end) | ||
750 | |||
751 | describe("fs.remove_dir_tree_if_empty", function() | ||
752 | local tmpfile | ||
753 | local tmpdir | ||
754 | local intdir | ||
755 | |||
756 | after_each(function() | ||
757 | if tmpfile then | ||
758 | os.remove(tmpfile) | ||
759 | tmpfile = nil | ||
760 | end | ||
761 | if intdir then | ||
762 | lfs.rmdir(intdir) | ||
763 | intdir = nil | ||
764 | end | ||
765 | if tmpdir then | ||
766 | lfs.rmdir(tmpdir) | ||
767 | tmpdir = nil | ||
768 | end | ||
769 | end) | ||
770 | |||
771 | it("removes the directory path specified by the argument if it is empty", function() | ||
772 | tmpdir = get_tmp_path() | ||
773 | lfs.mkdir(tmpdir) | ||
774 | fs.remove_dir_tree_if_empty(tmpdir) | ||
775 | assert.falsy(exists_file(tmpdir)) | ||
776 | end) | ||
777 | |||
778 | it("does nothing if the directory path specified by the argument is not empty", function() | ||
779 | tmpdir = get_tmp_path() | ||
780 | lfs.mkdir(tmpdir) | ||
781 | intdir = "/internaldir" | ||
782 | local dirpath = tmpdir .. intdir | ||
783 | lfs.mkdir(dirpath) | ||
784 | tmpfile = "/internalfile" | ||
785 | local filepath = dirpath .. tmpfile | ||
786 | fs.remove_dir_tree_if_empty(tmpdir) | ||
787 | assert.truthy(exists_file(dirpath)) | ||
788 | assert.truthy(exists_file(tmpdir)) | ||
789 | end) | ||
790 | end) | ||
791 | |||
792 | describe("fs.list_dir", function() | ||
793 | local intfile1 | ||
794 | local intfile2 | ||
795 | local intdir | ||
796 | local tmpdir | ||
797 | |||
798 | before_each(function() | ||
799 | if intfile1 then | ||
800 | os.remove(intfile1) | ||
801 | intfile1 = nil | ||
802 | end | ||
803 | if intfile2 then | ||
804 | os.remove(intfile2) | ||
805 | intfile2 = nil | ||
806 | end | ||
807 | if intdir then | ||
808 | lfs.rmdir(intdir) | ||
809 | intdir = nil | ||
810 | end | ||
811 | if tmpdir then | ||
812 | lfs.rmdir(tmpdir) | ||
813 | tmpdir = nil | ||
814 | end | ||
815 | end) | ||
816 | |||
817 | it("returns a table with the contents of the given directory", function() | ||
818 | tmpdir = get_tmp_path() | ||
819 | lfs.mkdir(tmpdir) | ||
820 | intfile1 = tmpdir .. "/intfile1" | ||
821 | create_file(intfile1) | ||
822 | intdir = tmpdir .. "/intdir" | ||
823 | lfs.mkdir(intdir) | ||
824 | intfile2 = intdir .. "/intfile2" | ||
825 | create_file(intfile2) | ||
826 | local result = fs.list_dir(tmpdir) | ||
827 | assert.same(#result, 2) | ||
828 | assert.truthy(result[1] == "intfile1" or result[1] == "intdir") | ||
829 | assert.truthy(result[2] == "intfile1" or result[2] == "intdir") | ||
830 | assert.is_not.same(result[1], result[2]) | ||
831 | end) | ||
832 | |||
833 | it("returns an empty table if the argument is a file", function() | ||
834 | intfile1 = get_tmp_path() | ||
835 | create_file(intfile1) | ||
836 | local result = fs.list_dir(intfile1) | ||
837 | assert.same(#result, 0) | ||
838 | end) | ||
839 | |||
840 | it("does nothing if the argument is nonexistent", function() | ||
841 | assert.same(fs.list_dir("/nonexistent"), {}) | ||
842 | end) | ||
843 | |||
844 | it("does nothing if the argument doesn't have the proper permissions", function() | ||
845 | tmpdir = get_tmp_path() | ||
846 | lfs.mkdir(tmpdir) | ||
847 | make_unreadable(tmpdir) | ||
848 | assert.same(fs.list_dir(tmpdir), {}) | ||
849 | end) | ||
850 | end) | ||
851 | |||
852 | describe("fs.copy", function() | ||
853 | local srcfile | ||
854 | local dstfile | ||
855 | local tmpdir | ||
856 | |||
857 | after_each(function() | ||
858 | if srcfile then | ||
859 | os.remove(srcfile) | ||
860 | srcfile = nil | ||
861 | end | ||
862 | if dstfile then | ||
863 | os.remove(dstfile) | ||
864 | dstfile = nil | ||
865 | end | ||
866 | if tmpdir then | ||
867 | lfs.rmdir(tmpdir) | ||
868 | tmpdir = nil | ||
869 | end | ||
870 | end) | ||
871 | |||
872 | it("returns true and copies the contents and the permissions of the source file to the destination file", function() | ||
873 | srcfile = get_tmp_path() | ||
874 | create_file(srcfile, srccontent) | ||
875 | dstfile = get_tmp_path() | ||
876 | assert.truthy(fs.copy(srcfile, dstfile)) | ||
877 | local fd = assert(io.open(dstfile, "r")) | ||
878 | local dstcontent = fd:read("*a") | ||
879 | assert.same("foo", dstcontent) | ||
880 | if posix_ok then | ||
881 | assert.same(lfs.attributes(srcfile, "permissions"), lfs.attributes(dstfile, "permissions")) | ||
882 | end | ||
883 | end) | ||
884 | |||
885 | it("returns true and copies contents of the source file to the destination file with custom permissions", function() | ||
886 | srcfile = get_tmp_path() | ||
887 | create_file(srcfile, srccontent) | ||
888 | dstfile = get_tmp_path() | ||
889 | assert.truthy(fs.copy(srcfile, dstfile, "exec")) | ||
890 | local fd = assert(io.open(dstfile, "r")) | ||
891 | local dstcontent = fd:read("*a") | ||
892 | assert.same("foo", dstcontent) | ||
893 | end) | ||
894 | |||
895 | it("returns false and does nothing if the source file does not exist", function() | ||
896 | srcfile = get_tmp_path() | ||
897 | dstfile = get_tmp_path() | ||
898 | local ok, err = fs.copy(srcfile, dstfile, nil) | ||
899 | assert.falsy(ok) | ||
900 | assert.not_match("are the same file", err) | ||
901 | assert.falsy(exists_file(dstfile)) | ||
902 | end) | ||
903 | |||
904 | it("returns false and does nothing if the source file doesn't have the proper permissions", function() | ||
905 | srcfile = get_tmp_path() | ||
906 | create_file(srcfile) | ||
907 | make_unreadable(srcfile) | ||
908 | dstfile = get_tmp_path() | ||
909 | assert.falsy(fs.copy(srcfile, dstfile, nil)) | ||
910 | assert.falsy(exists_file(dstfile)) | ||
911 | end) | ||
912 | |||
913 | it("returns false and does nothing if the destination file directory doesn't have the proper permissions", function() | ||
914 | srcfile = get_tmp_path() | ||
915 | create_file(srcfile) | ||
916 | tmpdir = get_tmp_path() | ||
917 | lfs.mkdir(tmpdir) | ||
918 | make_unwritable(tmpdir) | ||
919 | dstfile = tmpdir .. "/dstfile" | ||
920 | assert.falsy(fs.copy(srcfile, dstfile, nil)) | ||
921 | assert(fs.set_permissions(tmpdir, "exec", "all")) | ||
922 | assert.falsy(exists_file(dstfile)) | ||
923 | end) | ||
924 | end) | ||
925 | |||
926 | describe("fs.copy_contents", function() | ||
927 | local srcfile | ||
928 | local dstfile | ||
929 | local srcintdir | ||
930 | local dstintdir | ||
931 | local srcdir | ||
932 | local dstdir | ||
933 | |||
934 | after_each(function() | ||
935 | if srcfile then | ||
936 | os.remove(srcfile) | ||
937 | srcfile = nil | ||
938 | end | ||
939 | if dstfile then | ||
940 | os.remove(dstfile) | ||
941 | dstfile = nil | ||
942 | end | ||
943 | if srcintdir then | ||
944 | lfs.rmdir(srcintdir) | ||
945 | srcintdir = nil | ||
946 | end | ||
947 | if dstintdir then | ||
948 | lfs.rmdir(dstintdir) | ||
949 | dstintdir = nil | ||
950 | end | ||
951 | if srcdir then | ||
952 | lfs.rmdir(srcdir) | ||
953 | srcdir = nil | ||
954 | end | ||
955 | if dstdir then | ||
956 | lfs.rmdir(dstdir) | ||
957 | dstdir = nil | ||
958 | end | ||
959 | end) | ||
960 | |||
961 | local create_dir_tree = function() | ||
962 | srcdir = get_tmp_path() | ||
963 | lfs.mkdir(srcdir) | ||
964 | srcintdir = srcdir .. "/internaldir" | ||
965 | lfs.mkdir(srcintdir) | ||
966 | srcfile = srcintdir .. "/internalfile" | ||
967 | create_file(srcfile) | ||
968 | dstdir = get_tmp_path() | ||
969 | end | ||
970 | |||
971 | it("returns true and copies the contents (with their permissions) of the source dir to the destination dir", function() | ||
972 | create_dir_tree() | ||
973 | assert.truthy(fs.copy_contents(srcdir, dstdir)) | ||
974 | assert.truthy(exists_file(dstdir)) | ||
975 | dstintdir = dstdir .. "/internaldir" | ||
976 | assert.truthy(exists_file(dstintdir)) | ||
977 | dstfile = dstdir .. "/internaldir/internalfile" | ||
978 | local fd = assert(io.open(dstfile, "r")) | ||
979 | local dstfilecontent = fd:read("*a") | ||
980 | assert.same("foo", dstfilecontent) | ||
981 | if posix_ok then | ||
982 | assert.same(lfs.attributes(srcfile, "permissions"), lfs.attributes(dstfile, "permissions")) | ||
983 | end | ||
984 | end) | ||
985 | |||
986 | it("returns true and copies the contents of the source dir to the destination dir with custom permissions", function() | ||
987 | create_dir_tree() | ||
988 | assert.truthy(fs.copy_contents(srcdir, dstdir, "read")) | ||
989 | assert.truthy(exists_file(dstdir)) | ||
990 | dstintdir = dstdir .. "/internaldir" | ||
991 | assert.truthy(exists_file(dstintdir)) | ||
992 | dstfile = dstdir .. "/internaldir/internalfile" | ||
993 | local fd = assert(io.open(dstfile, "r")) | ||
994 | local dstfilecontent = fd:read("*a") | ||
995 | assert.same("foo", dstfilecontent) | ||
996 | end) | ||
997 | |||
998 | it("returns false and does nothing if the source dir doesn't exist", function() | ||
999 | srcdir = get_tmp_path() | ||
1000 | dstdir = get_tmp_path() | ||
1001 | assert.falsy(fs.copy_contents(srcdir, dstdir)) | ||
1002 | assert.falsy(exists_file(dstdir)) | ||
1003 | end) | ||
1004 | |||
1005 | it("returns false if the source argument is a file", function() | ||
1006 | srcdir = get_tmp_path() | ||
1007 | create_file(srcdir) | ||
1008 | dstdir = get_tmp_path() | ||
1009 | assert.falsy(fs.copy_contents(srcdir, dstdir)) | ||
1010 | assert.falsy(exists_file(dstdir)) | ||
1011 | end) | ||
1012 | |||
1013 | it("returns false and does nothing if the source dir doesn't have the proper permissions", function() | ||
1014 | create_dir_tree() | ||
1015 | make_unreadable(srcdir) | ||
1016 | assert.falsy(fs.copy_contents(srcdir, dstdir)) | ||
1017 | assert.falsy(exists_file(dstdir .. "/internaldir")) | ||
1018 | assert.falsy(exists_file(dstdir .. "/internalfile")) | ||
1019 | end) | ||
1020 | end) | ||
1021 | |||
1022 | describe("fs.find", function() | ||
1023 | local tmpdir | ||
1024 | local intdir | ||
1025 | local intfile1 | ||
1026 | local intfile2 | ||
1027 | |||
1028 | after_each(function() | ||
1029 | if intfile1 then | ||
1030 | os.remove(intfile1) | ||
1031 | intfile1 = nil | ||
1032 | end | ||
1033 | if intfile2 then | ||
1034 | os.remove(intfile2) | ||
1035 | intfile2 = nil | ||
1036 | end | ||
1037 | if intdir then | ||
1038 | lfs.rmdir(intdir) | ||
1039 | intdir = nil | ||
1040 | end | ||
1041 | if tmpdir then | ||
1042 | lfs.rmdir(tmpdir) | ||
1043 | tmpdir = nil | ||
1044 | end | ||
1045 | end) | ||
1046 | |||
1047 | local create_dir_tree = function() | ||
1048 | tmpdir = get_tmp_path() | ||
1049 | lfs.mkdir(tmpdir) | ||
1050 | intfile1 = tmpdir .. "/intfile1" | ||
1051 | create_file(intfile1) | ||
1052 | intdir = tmpdir .. "/intdir" | ||
1053 | lfs.mkdir(intdir) | ||
1054 | intfile2 = intdir .. "/intfile2" | ||
1055 | create_file(intfile2) | ||
1056 | end | ||
1057 | |||
1058 | it("returns a table of all the contents in the directory given as argument", function() | ||
1059 | create_dir_tree() | ||
1060 | local contents = {} | ||
1061 | local count = 0 | ||
1062 | for _, file in pairs(fs.find(tmpdir)) do | ||
1063 | contents[file] = true | ||
1064 | count = count + 1 | ||
1065 | end | ||
1066 | assert.same(count, 3) | ||
1067 | assert.is_not.same(contents[tmpdir], true) | ||
1068 | assert.same(contents["intfile1"], true) | ||
1069 | assert.same(contents["intdir"], true) | ||
1070 | assert.same(contents["intdir/intfile2"], true) | ||
1071 | end) | ||
1072 | |||
1073 | it("uses the current working directory if the argument is nil", function() | ||
1074 | create_dir_tree() | ||
1075 | local olddir = fs.current_dir() | ||
1076 | fs.change_dir(intdir) | ||
1077 | local contents = {} | ||
1078 | local count = 0 | ||
1079 | for _, file in pairs(fs.find()) do | ||
1080 | contents[file] = true | ||
1081 | count = count + 1 | ||
1082 | end | ||
1083 | assert.same(count, 1) | ||
1084 | assert.is_not.same(contents["intfile1"], true) | ||
1085 | assert.is_not.same(contents["intdir"], true) | ||
1086 | assert.same(contents["intfile2"], true) | ||
1087 | fs.change_dir(olddir) | ||
1088 | end) | ||
1089 | |||
1090 | it("returns an empty table if the argument is nonexistent", function() | ||
1091 | local contents = fs.find("/nonexistent") | ||
1092 | local count = 0 | ||
1093 | for _, file in pairs(contents) do | ||
1094 | count = count + 1 | ||
1095 | end | ||
1096 | assert.same(count, 0) | ||
1097 | end) | ||
1098 | |||
1099 | it("returns an empty table if the argument is a file", function() | ||
1100 | intfile1 = get_tmp_path() | ||
1101 | create_file(intfile1) | ||
1102 | local contents = fs.find(intfile1) | ||
1103 | local count = 0 | ||
1104 | for _, file in pairs(contents) do | ||
1105 | count = count + 1 | ||
1106 | end | ||
1107 | assert.same(count, 0) | ||
1108 | end) | ||
1109 | |||
1110 | it("does nothing if the argument doesn't have the proper permissions", function() | ||
1111 | tmpdir = get_tmp_path() | ||
1112 | lfs.mkdir(tmpdir) | ||
1113 | make_unreadable(tmpdir) | ||
1114 | assert.same(fs.find(tmpdir), {}) | ||
1115 | end) | ||
1116 | end) | ||
1117 | |||
1118 | describe("fs.move", function() | ||
1119 | local srcfile | ||
1120 | local dstfile | ||
1121 | local tmpdir | ||
1122 | |||
1123 | after_each(function() | ||
1124 | if srcfile then | ||
1125 | os.remove(srcfile) | ||
1126 | srcfile = nil | ||
1127 | end | ||
1128 | if dstfile then | ||
1129 | os.remove(dstfile) | ||
1130 | dstfile = nil | ||
1131 | end | ||
1132 | if tmpdir then | ||
1133 | lfs.rmdir(tmpdir) | ||
1134 | tmpdir = nil | ||
1135 | end | ||
1136 | end) | ||
1137 | |||
1138 | it("returns true and moves the source (together with its permissions) to the destination", function() | ||
1139 | srcfile = get_tmp_path() | ||
1140 | create_file(srcfile) | ||
1141 | dstfile = get_tmp_path() | ||
1142 | local oldperms = lfs.attributes(srcfile, "permissions") | ||
1143 | assert.truthy(fs.move(srcfile, dstfile)) | ||
1144 | assert.truthy(fs.exists(dstfile)) | ||
1145 | assert.falsy(fs.exists(srcfile)) | ||
1146 | local fd = assert(io.open(dstfile, "r")) | ||
1147 | local dstcontents = assert(fd:read("*a")) | ||
1148 | assert.same(dstcontents, "foo") | ||
1149 | if posix_ok then | ||
1150 | assert.same(oldperms, lfs.attributes(dstfile, "permissions")) | ||
1151 | end | ||
1152 | end) | ||
1153 | |||
1154 | it("returns true and moves the source (with custom permissions) to the destination", function() | ||
1155 | srcfile = get_tmp_path() | ||
1156 | create_file(srcfile) | ||
1157 | dstfile = get_tmp_path() | ||
1158 | assert.truthy(fs.move(srcfile, dstfile, "read")) | ||
1159 | assert.truthy(fs.exists(dstfile)) | ||
1160 | assert.falsy(fs.exists(srcfile)) | ||
1161 | local fd = assert(io.open(dstfile, "r")) | ||
1162 | local dstcontents = assert(fd:read("*a")) | ||
1163 | assert.same(dstcontents, "foo") | ||
1164 | end) | ||
1165 | |||
1166 | it("returns false and does nothing if the source doesn't exist", function() | ||
1167 | dstfile = get_tmp_path() | ||
1168 | assert.falsy(fs.move("/nonexistent", dstfile)) | ||
1169 | assert.falsy(fs.exists(dstfile)) | ||
1170 | end) | ||
1171 | |||
1172 | it("returns false and does nothing if the destination already exists", function() | ||
1173 | srcfile = get_tmp_path() | ||
1174 | create_file(srcfile) | ||
1175 | dstfile = get_tmp_path() | ||
1176 | create_file(dstfile, "bar") | ||
1177 | assert.falsy(fs.move(srcfile, dstfile)) | ||
1178 | assert.truthy(fs.exists(srcfile)) | ||
1179 | local fd = assert(io.open(dstfile, "r")) | ||
1180 | local dstcontents = assert(fd:read("*a")) | ||
1181 | assert.same(dstcontents, "bar") | ||
1182 | end) | ||
1183 | |||
1184 | it("returns false and does nothing if the destination path doesn't have the proper permissions", function() | ||
1185 | srcfile = get_tmp_path() | ||
1186 | create_file(srcfile) | ||
1187 | tmpdir = get_tmp_path() | ||
1188 | lfs.mkdir(tmpdir) | ||
1189 | make_unwritable(tmpdir) | ||
1190 | assert.falsy(fs.move(srcfile, tmpdir .. "/dstfile")) | ||
1191 | assert.falsy(fs.exists(tmpdir .. "/dstfile")) | ||
1192 | end) | ||
1193 | end) | ||
1194 | |||
1195 | describe("fs.is_lua", function() | ||
1196 | local tmpfile | ||
1197 | |||
1198 | after_each(function() | ||
1199 | if tmpfile then | ||
1200 | os.remove(tmpfile) | ||
1201 | tmpfile = nil | ||
1202 | end | ||
1203 | end) | ||
1204 | |||
1205 | it("returns true if the argument is a valid lua script", function() | ||
1206 | tmpfile = get_tmp_path() | ||
1207 | create_file(tmpfile, "print(\"foo\")") | ||
1208 | assert.truthy(fs.is_lua(tmpfile)) | ||
1209 | end) | ||
1210 | |||
1211 | it("returns true if the argument is a valid lua script with shebang", function() | ||
1212 | tmpfile = get_tmp_path() | ||
1213 | create_file(tmpfile, "#!/usr/bin/env lua\n\nprint(\"foo\")") | ||
1214 | assert.truthy(fs.is_lua(tmpfile)) | ||
1215 | end) | ||
1216 | |||
1217 | it("returns false if the argument is not a valid lua script", function() | ||
1218 | tmpfile = os.tmpname() | ||
1219 | create_file(tmpfile) | ||
1220 | assert.falsy(fs.is_lua(tmpfile)) | ||
1221 | end) | ||
1222 | |||
1223 | it("returns false if the argument is a valid lua script but doesn't have the proper permissions", function() | ||
1224 | tmpfile = get_tmp_path() | ||
1225 | create_file(tmpfile, "print(\"foo\")") | ||
1226 | make_unreadable(tmpfile) | ||
1227 | assert.falsy(fs.is_lua(tmpfile)) | ||
1228 | end) | ||
1229 | end) | ||
1230 | |||
1231 | describe("fs.delete", function() | ||
1232 | local tmpfile1 | ||
1233 | local tmpfile2 | ||
1234 | local tmpintdir | ||
1235 | local tmpdir | ||
1236 | |||
1237 | after_each(function() | ||
1238 | if tmpfile1 then | ||
1239 | os.remove(tmpfile1) | ||
1240 | tmpfile1 = nil | ||
1241 | end | ||
1242 | if tmpfile2 then | ||
1243 | os.remove(tmpfile2) | ||
1244 | tmpfile2 = nil | ||
1245 | end | ||
1246 | if tmpintdir then | ||
1247 | lfs.rmdir(tmpintdir) | ||
1248 | tmpintdir = nil | ||
1249 | end | ||
1250 | if tmpdir then | ||
1251 | lfs.rmdir(tmpdir) | ||
1252 | tmpdir = nil | ||
1253 | end | ||
1254 | end) | ||
1255 | |||
1256 | local create_dir_tree = function() | ||
1257 | tmpdir = get_tmp_path() | ||
1258 | lfs.mkdir(tmpdir) | ||
1259 | tmpintdir = tmpdir .. "/internaldir" | ||
1260 | lfs.mkdir(tmpintdir) | ||
1261 | tmpfile1 = tmpdir .. "/internalfile1" | ||
1262 | create_file(tmpfile1) | ||
1263 | tmpfile2 = tmpdir .. "/internalfile2" | ||
1264 | create_file(tmpfile2) | ||
1265 | end | ||
1266 | |||
1267 | it("deletes the file specified by the argument", function() | ||
1268 | tmpfile1 = get_tmp_path() | ||
1269 | tmpfile2 = get_tmp_path() | ||
1270 | fs.delete(tmpfile1) | ||
1271 | fs.delete(tmpfile2) | ||
1272 | assert.falsy(exists_file(tmpfile1)) | ||
1273 | assert.falsy(exists_file(tmpfile2)) | ||
1274 | end) | ||
1275 | |||
1276 | it("deletes the contents of the directory specified by the argument", function() | ||
1277 | create_dir_tree() | ||
1278 | fs.delete(tmpdir) | ||
1279 | assert.falsy(exists_file(tmpfile2)) | ||
1280 | assert.falsy(exists_file(tmpintdir)) | ||
1281 | assert.falsy(exists_file(tmpfile1)) | ||
1282 | assert.falsy(exists_file(tmpdir)) | ||
1283 | end) | ||
1284 | end) | ||
1285 | |||
1286 | describe("fs.download #mock", function() | ||
1287 | local tmpfile | ||
1288 | local tmpdir | ||
1289 | |||
1290 | setup(function() | ||
1291 | test_env.mock_server_init() | ||
1292 | end) | ||
1293 | |||
1294 | teardown(function() | ||
1295 | test_env.mock_server_done() | ||
1296 | end) | ||
1297 | |||
1298 | after_each(function() | ||
1299 | if tmpfile then | ||
1300 | os.remove(tmpfile) | ||
1301 | tmpfile = nil | ||
1302 | end | ||
1303 | if tmpdir then | ||
1304 | lfs.rmdir(tmpdir) | ||
1305 | tmpdir = nil | ||
1306 | end | ||
1307 | end) | ||
1308 | |||
1309 | it("returns true and fetches the url argument into the specified filename", function() | ||
1310 | tmpfile = get_tmp_path() | ||
1311 | assert.truthy(fs.download("http://localhost:8080/file/a_rock.lua", tmpfile)) | ||
1312 | local fd = assert(io.open(tmpfile, "r")) | ||
1313 | local downloadcontent = assert(fd:read("*a")) | ||
1314 | fd:close() | ||
1315 | fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) | ||
1316 | local originalcontent = assert(fd:read("*a")) | ||
1317 | fd:close() | ||
1318 | assert.same(downloadcontent, originalcontent) | ||
1319 | end) | ||
1320 | |||
1321 | it("returns true and fetches the url argument into a file whose name matches the basename of the url if the filename argument is not given", function() | ||
1322 | tmpdir = get_tmp_path() | ||
1323 | lfs.mkdir(tmpdir) | ||
1324 | fs.change_dir(tmpdir) | ||
1325 | assert.truthy(fs.download("http://localhost:8080/file/a_rock.lua")) | ||
1326 | tmpfile = tmpdir .. "/a_rock.lua" | ||
1327 | local fd = assert(io.open(tmpfile, "r")) | ||
1328 | local downloadcontent = assert(fd:read("*a")) | ||
1329 | fd:close() | ||
1330 | fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) | ||
1331 | local originalcontent = assert(fd:read("*a")) | ||
1332 | fd:close() | ||
1333 | assert.same(downloadcontent, originalcontent) | ||
1334 | fs.pop_dir() | ||
1335 | end) | ||
1336 | |||
1337 | it("returns false and does nothing if the url argument contains a nonexistent file", function() | ||
1338 | tmpfile = get_tmp_path() | ||
1339 | assert.falsy(fs.download("http://localhost:8080/file/nonexistent", tmpfile)) | ||
1340 | end) | ||
1341 | |||
1342 | it("returns false and does nothing if the url argument is invalid", function() | ||
1343 | assert.falsy(fs.download("invalidurl")) | ||
1344 | end) | ||
1345 | end) | ||
1346 | |||
1347 | describe("fs.zip", function() | ||
1348 | local tmpdir | ||
1349 | local olddir | ||
1350 | |||
1351 | before_each(function() | ||
1352 | olddir = lfs.currentdir() | ||
1353 | tmpdir = get_tmp_path() | ||
1354 | lfs.mkdir(tmpdir) | ||
1355 | chdir(tmpdir) | ||
1356 | |||
1357 | write_file("file1", "content1", finally) | ||
1358 | write_file("file2", "content2", finally) | ||
1359 | lfs.mkdir("dir") | ||
1360 | write_file("dir/file3", "content3", finally) | ||
1361 | end) | ||
1362 | |||
1363 | after_each(function() | ||
1364 | if olddir then | ||
1365 | chdir(olddir) | ||
1366 | if tmpdir then | ||
1367 | lfs.rmdir(tmpdir .. "/dir") | ||
1368 | lfs.rmdir(tmpdir) | ||
1369 | end | ||
1370 | end | ||
1371 | end) | ||
1372 | |||
1373 | it("returns true and creates a zip archive of the given files", function() | ||
1374 | assert.truthy(fs.zip("archive.zip", "file1", "file2", "dir")) | ||
1375 | assert.truthy(exists_file("archive.zip")) | ||
1376 | end) | ||
1377 | |||
1378 | it("returns false and does nothing if the files specified in the arguments are invalid", function() | ||
1379 | assert.falsy(fs.zip("archive.zip", "nonexistent")) | ||
1380 | assert.falsy(exists_file("nonexistent")) | ||
1381 | end) | ||
1382 | end) | ||
1383 | |||
1384 | describe("fs.bunzip2", function() | ||
1385 | |||
1386 | it("uncompresses a .bz2 file", function() | ||
1387 | local input = testing_paths.fixtures_dir .. "/abc.bz2" | ||
1388 | local output = os.tmpname() | ||
1389 | assert.truthy(fs.bunzip2(input, output)) | ||
1390 | local fd = io.open(output, "r") | ||
1391 | local content = fd:read("*a") | ||
1392 | fd:close() | ||
1393 | assert.same(300000, #content) | ||
1394 | local abc = ("a"):rep(100000)..("b"):rep(100000)..("c"):rep(100000) | ||
1395 | assert.same(abc, content) | ||
1396 | end) | ||
1397 | |||
1398 | end) | ||
1399 | |||
1400 | describe("fs.unzip", function() | ||
1401 | local tmpdir | ||
1402 | local olddir | ||
1403 | |||
1404 | before_each(function() | ||
1405 | olddir = lfs.currentdir() | ||
1406 | tmpdir = get_tmp_path() | ||
1407 | lfs.mkdir(tmpdir) | ||
1408 | chdir(tmpdir) | ||
1409 | |||
1410 | write_file("file1", "content1", finally) | ||
1411 | write_file("file2", "content2", finally) | ||
1412 | lfs.mkdir("dir") | ||
1413 | write_file("dir/file3", "content3", finally) | ||
1414 | end) | ||
1415 | |||
1416 | after_each(function() | ||
1417 | if olddir then | ||
1418 | chdir(olddir) | ||
1419 | if tmpdir then | ||
1420 | lfs.rmdir(tmpdir .. "/dir") | ||
1421 | lfs.rmdir(tmpdir) | ||
1422 | end | ||
1423 | end | ||
1424 | end) | ||
1425 | |||
1426 | it("returns true and unzips the given zip archive", function() | ||
1427 | assert.truthy(fs.zip("archive.zip", "file1", "file2", "dir")) | ||
1428 | os.remove("file1") | ||
1429 | os.remove("file2") | ||
1430 | lfs.rmdir("dir") | ||
1431 | |||
1432 | assert.truthy(fs.unzip("archive.zip")) | ||
1433 | assert.truthy(exists_file("file1")) | ||
1434 | assert.truthy(exists_file("file2")) | ||
1435 | assert.truthy(exists_file("dir/file3")) | ||
1436 | |||
1437 | local fd | ||
1438 | |||
1439 | fd = assert(io.open("file1", "r")) | ||
1440 | assert.same(fd:read("*a"), "content1") | ||
1441 | fd:close() | ||
1442 | |||
1443 | fd = assert(io.open("file2", "r")) | ||
1444 | assert.same(fd:read("*a"), "content2") | ||
1445 | fd:close() | ||
1446 | |||
1447 | fd = assert(io.open("dir/file3", "r")) | ||
1448 | assert.same(fd:read("*a"), "content3") | ||
1449 | fd:close() | ||
1450 | end) | ||
1451 | |||
1452 | it("does nothing if the given archive is invalid", function() | ||
1453 | assert.falsy(fs.unzip("archive.zip")) | ||
1454 | end) | ||
1455 | end) | ||
1456 | |||
1457 | describe("fs.wrap_script", function() | ||
1458 | local tmpdir | ||
1459 | local olddir | ||
1460 | |||
1461 | before_each(function() | ||
1462 | olddir = lfs.currentdir() | ||
1463 | tmpdir = get_tmp_path() | ||
1464 | lfs.mkdir(tmpdir) | ||
1465 | chdir(tmpdir) | ||
1466 | end) | ||
1467 | |||
1468 | after_each(function() | ||
1469 | if olddir then | ||
1470 | chdir(olddir) | ||
1471 | if tmpdir then | ||
1472 | lfs.rmdir(tmpdir) | ||
1473 | end | ||
1474 | end | ||
1475 | end) | ||
1476 | |||
1477 | it("produces a wrapper for a Lua script", function() | ||
1478 | write_file("my_script", "io.write('Hello ' .. arg[1])", finally) | ||
1479 | path.use_tree(testing_paths.testing_tree) | ||
1480 | local wrapper_name = fs.absolute_name("wrapper") .. test_env.wrapper_extension | ||
1481 | fs.wrap_script("my_script", wrapper_name, "one", nil, nil, "World") | ||
1482 | local pd = assert(io.popen(wrapper_name)) | ||
1483 | local data = pd:read("*a") | ||
1484 | pd:close() | ||
1485 | assert.same("Hello World", data) | ||
1486 | end) | ||
1487 | end) | ||
1488 | |||
1489 | describe("fs.copy_binary", function() | ||
1490 | local tmpdir | ||
1491 | local olddir | ||
1492 | |||
1493 | before_each(function() | ||
1494 | olddir = lfs.currentdir() | ||
1495 | tmpdir = get_tmp_path() | ||
1496 | lfs.mkdir(tmpdir) | ||
1497 | chdir(tmpdir) | ||
1498 | |||
1499 | write_file("test.exe", "", finally) | ||
1500 | end) | ||
1501 | |||
1502 | after_each(function() | ||
1503 | if olddir then | ||
1504 | chdir(olddir) | ||
1505 | if tmpdir then | ||
1506 | lfs.rmdir(tmpdir) | ||
1507 | end | ||
1508 | end | ||
1509 | end) | ||
1510 | |||
1511 | it("returns true and copies the given binary file to the file specified in the dest argument", function() | ||
1512 | assert.truthy(fs.copy_binary("test.exe", lfs.currentdir() .. "/copy.exe")) | ||
1513 | assert.truthy(exists_file("copy.exe")) | ||
1514 | if is_win then | ||
1515 | assert.truthy(exists_file("test.lua")) | ||
1516 | local fd = assert(io.open("test.lua", "r")) | ||
1517 | local content = assert(fd:read("*a")) | ||
1518 | assert.truthy(content:find("package.path", 1, true)) | ||
1519 | assert.truthy(content:find("package.cpath", 1, true)) | ||
1520 | fd:close() | ||
1521 | end | ||
1522 | end) | ||
1523 | |||
1524 | it("returns false and does nothing if the source file is invalid", function() | ||
1525 | assert.falsy(fs.copy_binary("invalid.exe", "copy.exe")) | ||
1526 | end) | ||
1527 | end) | ||
1528 | |||
1529 | describe("fs.modules", function() | ||
1530 | local tmpdir | ||
1531 | local olddir | ||
1532 | local oldpath | ||
1533 | |||
1534 | before_each(function() | ||
1535 | olddir = lfs.currentdir() | ||
1536 | tmpdir = get_tmp_path() | ||
1537 | lfs.mkdir(tmpdir) | ||
1538 | chdir(tmpdir) | ||
1539 | lfs.mkdir("lib") | ||
1540 | write_file("lib/module1.lua", "", finally) | ||
1541 | write_file("lib/module2.lua", "", finally) | ||
1542 | write_file("lib/module1.LuA", "", finally) | ||
1543 | write_file("lib/non_lua", "", finally) | ||
1544 | lfs.mkdir("lib/internal") | ||
1545 | write_file("lib/internal/module11.lua", "", finally) | ||
1546 | write_file("lib/internal/module22.lua", "", finally) | ||
1547 | |||
1548 | oldpath = package.path | ||
1549 | package.path = package.path .. tmpdir .. "/?.lua;" | ||
1550 | end) | ||
1551 | |||
1552 | after_each(function() | ||
1553 | if olddir then | ||
1554 | chdir(olddir) | ||
1555 | if tmpdir then | ||
1556 | lfs.rmdir(tmpdir .. "/lib/internal") | ||
1557 | lfs.rmdir(tmpdir .. "/lib") | ||
1558 | lfs.rmdir(tmpdir) | ||
1559 | end | ||
1560 | end | ||
1561 | if oldpath then | ||
1562 | package.path = oldpath | ||
1563 | end | ||
1564 | end) | ||
1565 | |||
1566 | it("returns a table of the lua modules at a specific require path", function() | ||
1567 | local result | ||
1568 | |||
1569 | result = fs.modules("lib") | ||
1570 | assert.same(#result, 2) | ||
1571 | assert.truthy(result[1] == "module1" or result[2] == "module1") | ||
1572 | assert.truthy(result[1] == "module2" or result[2] == "module2") | ||
1573 | |||
1574 | result = fs.modules("lib.internal") | ||
1575 | assert.same(#result, 2) | ||
1576 | assert.truthy(result[1] == "module11" or result[2] == "module11") | ||
1577 | assert.truthy(result[1] == "module22" or result[2] == "module22") | ||
1578 | end) | ||
1579 | |||
1580 | it("returns an empty table if the modules couldn't be found in package.path", function() | ||
1581 | package.path = "" | ||
1582 | assert.same(fs.modules("lib"), {}) | ||
1583 | end) | ||
1584 | end) | ||
1585 | |||
1586 | describe("#unix fs._unix_rwx_to_number", function() | ||
1587 | |||
1588 | it("converts permissions in rwx notation to numeric ones", function() | ||
1589 | assert.same(tonumber("0644", 8), fs._unix_rwx_to_number("rw-r--r--")) | ||
1590 | assert.same(tonumber("0755", 8), fs._unix_rwx_to_number("rwxr-xr-x")) | ||
1591 | assert.same(tonumber("0000", 8), fs._unix_rwx_to_number("---------")) | ||
1592 | assert.same(tonumber("0777", 8), fs._unix_rwx_to_number("rwxrwxrwx")) | ||
1593 | assert.same(tonumber("0700", 8), fs._unix_rwx_to_number("rwx------")) | ||
1594 | assert.same(tonumber("0600", 8), fs._unix_rwx_to_number("rw-------")) | ||
1595 | end) | ||
1596 | |||
1597 | it("produces a negated mask if asked to", function() | ||
1598 | assert.same(tonumber("0133", 8), fs._unix_rwx_to_number("rw-r--r--", true)) | ||
1599 | assert.same(tonumber("0022", 8), fs._unix_rwx_to_number("rwxr-xr-x", true)) | ||
1600 | assert.same(tonumber("0777", 8), fs._unix_rwx_to_number("---------", true)) | ||
1601 | assert.same(tonumber("0000", 8), fs._unix_rwx_to_number("rwxrwxrwx", true)) | ||
1602 | assert.same(tonumber("0077", 8), fs._unix_rwx_to_number("rwx------", true)) | ||
1603 | assert.same(tonumber("0177", 8), fs._unix_rwx_to_number("rw-------", true)) | ||
1604 | end) | ||
1605 | end) | ||
1606 | |||
1607 | end) | ||
diff --git a/spec/unit/fun_spec.lua b/spec/unit/fun_spec.lua new file mode 100644 index 00000000..9844ec27 --- /dev/null +++ b/spec/unit/fun_spec.lua | |||
@@ -0,0 +1,130 @@ | |||
1 | local test_env = require("spec.util.test_env") | ||
2 | local testing_paths = test_env.testing_paths | ||
3 | |||
4 | test_env.unload_luarocks() | ||
5 | local fun = require("luarocks.fun") | ||
6 | |||
7 | describe("luarocks.fun #unit", function() | ||
8 | local runner | ||
9 | |||
10 | setup(function() | ||
11 | runner = require("luacov.runner") | ||
12 | runner.init(testing_paths.testrun_dir .. "/luacov.config") | ||
13 | runner.tick = true | ||
14 | end) | ||
15 | |||
16 | teardown(function() | ||
17 | runner.shutdown() | ||
18 | end) | ||
19 | |||
20 | describe("fun.concat", function() | ||
21 | it("returns the concatenation of the two tables given as arguments", function() | ||
22 | local t1, t2 | ||
23 | |||
24 | t1 = {1, 2, 3} | ||
25 | t2 = {4, 5, 6} | ||
26 | assert.same(fun.concat(t1, t2), {1, 2, 3, 4, 5, 6}) | ||
27 | assert.same(fun.concat(t2, t1), {4, 5, 6, 1, 2, 3}) | ||
28 | t1 = {1, 2, 3} | ||
29 | t2 = {} | ||
30 | assert.same(fun.concat(t1, t2), {1, 2, 3}) | ||
31 | assert.same(fun.concat(t2, t1), {1, 2, 3}) | ||
32 | t1 = {} | ||
33 | t2 = {} | ||
34 | assert.same(fun.concat(t1, t2), {}) | ||
35 | end) | ||
36 | end) | ||
37 | |||
38 | describe("fun.contains", function() | ||
39 | it("checks whether a table contains a given value", function() | ||
40 | local t | ||
41 | |||
42 | t = {1, 2, 3} | ||
43 | assert.truthy(fun.contains(t, 1)) | ||
44 | assert.falsy(fun.contains(t, 4)) | ||
45 | t = {} | ||
46 | assert.falsy(fun.contains(t, 1)) | ||
47 | end) | ||
48 | end) | ||
49 | |||
50 | local addOne = function(x) return x + 1 end | ||
51 | |||
52 | describe("fun.map", function() | ||
53 | it("applies a function to each element in the given table and returns the results in a new table", function() | ||
54 | local t | ||
55 | |||
56 | t = {1, 2, 3} | ||
57 | assert.same(fun.map(t, addOne), {2, 3, 4}) | ||
58 | t = {} | ||
59 | assert.same(fun.map(t, addOne), {}) | ||
60 | end) | ||
61 | end) | ||
62 | |||
63 | describe("fun.traverse", function() | ||
64 | it("recursively applies a function to each element in a given table and returns the results in a new table", function() | ||
65 | local t | ||
66 | |||
67 | t = {1, 2, {3, 4, {5, 6}}} | ||
68 | assert.same(fun.traverse(t, addOne), {2, 3, {4, 5, {6, 7}}}) | ||
69 | t = {1, 2, {}, {1, {}, 2}} | ||
70 | assert.same(fun.traverse(t, addOne), {2, 3, {}, {2, {}, 3}}) | ||
71 | end) | ||
72 | end) | ||
73 | |||
74 | describe("fun.filter", function() | ||
75 | it("filters the elements in the given table and returns the result in a new table", function() | ||
76 | local t | ||
77 | |||
78 | t = {1, 2, "a", "b", 3} | ||
79 | assert.same(fun.filter(t, function(x) return type(x) == "number" end), {1, 2, 3}) | ||
80 | t = {2, 4, 7, 8} | ||
81 | assert.same(fun.filter(t, function(x) return x % 2 == 0 end), {2, 4, 8}) | ||
82 | end) | ||
83 | end) | ||
84 | |||
85 | describe("fun.reverse_in", function() | ||
86 | it("reverses the elements in the given table and returns the result in a new table", function() | ||
87 | local t | ||
88 | |||
89 | t = {1, 2, 3, 4} | ||
90 | assert.same(fun.reverse_in(t), {4, 3, 2, 1}) | ||
91 | t = {"a", "b", "c"} | ||
92 | assert.same(fun.reverse_in(t), {"c", "b", "a"}) | ||
93 | end) | ||
94 | end) | ||
95 | |||
96 | describe("fun.sort_in", function() | ||
97 | it("sorts the elements in the given table and returns the result in a new table", function() | ||
98 | local t | ||
99 | |||
100 | t = {4, 2, 3, 1} | ||
101 | assert.same(fun.sort_in(t), {1, 2, 3, 4}) | ||
102 | t = {"d", "a", "c", "b"} | ||
103 | assert.same(fun.sort_in(t), {"a", "b", "c", "d"}) | ||
104 | end) | ||
105 | end) | ||
106 | |||
107 | describe("fun.flip", function() | ||
108 | it("returns a function behaving as the one given in the argument but with the arguments interchanged", function() | ||
109 | local a, b = fun.flip(function(a, b) return a, b end)(5, 6) | ||
110 | assert.same(a, 6) | ||
111 | assert.same(b, 5) | ||
112 | end) | ||
113 | end) | ||
114 | |||
115 | describe("fun.partial", function() | ||
116 | it("partially applies the given arguments to the given function and returns it", function() | ||
117 | local addOne = fun.partial(function(x, y) return x + y end, 1) | ||
118 | assert.same(addOne(1), 2) | ||
119 | assert.same(addOne(2), 3) | ||
120 | |||
121 | local addTwo = fun.partial(function(x, y, z) return x + y + z end, 1, 1) | ||
122 | assert.same(addTwo(1), 3) | ||
123 | assert.same(addTwo(2), 4) | ||
124 | |||
125 | local addThree = fun.partial(function(x, y, z, t, u) return x + y + z + t + u end, 1, 1, 1) | ||
126 | assert.same(addThree(1, 1), 5) | ||
127 | assert.same(addThree(1, 2), 6) | ||
128 | end) | ||
129 | end) | ||
130 | end) | ||
diff --git a/spec/unit/persist_spec.lua b/spec/unit/persist_spec.lua new file mode 100644 index 00000000..f426fd83 --- /dev/null +++ b/spec/unit/persist_spec.lua | |||
@@ -0,0 +1,76 @@ | |||
1 | local test_env = require("spec.util.test_env") | ||
2 | local testing_paths = test_env.testing_paths | ||
3 | |||
4 | test_env.unload_luarocks() | ||
5 | local persist = require("luarocks.persist") | ||
6 | |||
7 | describe("luarocks.persist #unit", function() | ||
8 | local runner | ||
9 | |||
10 | setup(function() | ||
11 | runner = require("luacov.runner") | ||
12 | runner.init(testing_paths.testrun_dir .. "/luacov.config") | ||
13 | runner.tick = true | ||
14 | end) | ||
15 | |||
16 | teardown(function() | ||
17 | runner.shutdown() | ||
18 | end) | ||
19 | |||
20 | describe("persist.save_from_table_to_string", function() | ||
21 | it("simple table", function() | ||
22 | assert.are.same([[ | ||
23 | bar = 1234 | ||
24 | foo = "string" | ||
25 | ]], persist.save_from_table_to_string({foo = "string", bar = 1234})) | ||
26 | end) | ||
27 | |||
28 | it("nested tables", function() | ||
29 | assert.are.same([[ | ||
30 | bar = { | ||
31 | baz = "string" | ||
32 | } | ||
33 | foo = { | ||
34 | 1, 2, 3, 4 | ||
35 | } | ||
36 | ]], persist.save_from_table_to_string({foo = {1, 2, 3, 4}, bar = {baz = "string"}})) | ||
37 | end) | ||
38 | |||
39 | it("table with a keyword key (#947)", function() | ||
40 | assert.are.same([[ | ||
41 | bar = { | ||
42 | ["function"] = "foo" | ||
43 | } | ||
44 | ]], persist.save_from_table_to_string({bar = {["function"] = "foo"}})) | ||
45 | end) | ||
46 | |||
47 | it("strings with quotes", function() | ||
48 | assert.are.same([[ | ||
49 | bar = "a \\backslash?" | ||
50 | foo = "a \"quote\"?" | ||
51 | ]], persist.save_from_table_to_string({foo = 'a "quote"?', bar = 'a \\backslash?'})) | ||
52 | end) | ||
53 | |||
54 | it("multiline strings", function() | ||
55 | assert.are.same([===[ | ||
56 | bar = [==[ | ||
57 | ]] | ||
58 | ]=]]==] | ||
59 | foo = [[ | ||
60 | First line | ||
61 | Second line]] | ||
62 | ]===], persist.save_from_table_to_string({foo = "First line\nSecond line", bar = "]]\n]=]"})) | ||
63 | end) | ||
64 | |||
65 | it("multiline strings ending with brackets", function() | ||
66 | assert.are.same([===[ | ||
67 | bar = [==[ | ||
68 | ]] | ||
69 | ]=]==] | ||
70 | foo = [=[ | ||
71 | First line | ||
72 | Second line [1]]=] | ||
73 | ]===], persist.save_from_table_to_string({foo = "First line\nSecond line [1]", bar = "]]\n]="})) | ||
74 | end) | ||
75 | end) | ||
76 | end) | ||
diff --git a/spec/unit/rockspecs_spec.lua b/spec/unit/rockspecs_spec.lua new file mode 100644 index 00000000..5b0573fe --- /dev/null +++ b/spec/unit/rockspecs_spec.lua | |||
@@ -0,0 +1,126 @@ | |||
1 | |||
2 | local rockspecs = require("luarocks.rockspecs") | ||
3 | local cfg = require("luarocks.core.cfg") | ||
4 | local test_env = require("spec.util.test_env") | ||
5 | local lfs = require("lfs") | ||
6 | |||
7 | describe("luarocks.rockspecs #unit", function() | ||
8 | |||
9 | setup(function() | ||
10 | cfg.init() | ||
11 | end) | ||
12 | |||
13 | it("auto adds a build dependency for non-vendored build types", function() | ||
14 | local filename = "test-1.0-1.rockspec" | ||
15 | local rockspec = { | ||
16 | package = "test", | ||
17 | source = { | ||
18 | url = "", | ||
19 | }, | ||
20 | build = { | ||
21 | type = "foo" | ||
22 | }, | ||
23 | } | ||
24 | local globals = {} | ||
25 | local quick = true | ||
26 | |||
27 | local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) | ||
28 | |||
29 | assert(rockspec == out) | ||
30 | assert.same(rockspec.build_dependencies, { | ||
31 | { name = "luarocks-build-foo", constraints = {} }, | ||
32 | }) | ||
33 | end) | ||
34 | |||
35 | it("does not add a build dependency for non-vendored build type if it's already ther", function() | ||
36 | local filename = "test-1.0-1.rockspec" | ||
37 | local rockspec = { | ||
38 | package = "test", | ||
39 | source = { | ||
40 | url = "", | ||
41 | }, | ||
42 | build_dependencies = { | ||
43 | "luarocks-build-cpp >= 1.0", | ||
44 | }, | ||
45 | build = { | ||
46 | type = "cpp" | ||
47 | }, | ||
48 | } | ||
49 | local globals = {} | ||
50 | local quick = true | ||
51 | |||
52 | local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) | ||
53 | |||
54 | assert(rockspec == out) | ||
55 | |||
56 | assert.same(rockspec.build_dependencies, { | ||
57 | { name = "luarocks-build-cpp", constraints = { { op = ">=", version = { string = "1.0", 1, 0 } } } }, | ||
58 | }) | ||
59 | end) | ||
60 | |||
61 | it("does not add a build dependency for 'none' build type", function() | ||
62 | local filename = "test-1.0-1.rockspec" | ||
63 | local rockspec = { | ||
64 | package = "test", | ||
65 | source = { | ||
66 | url = "", | ||
67 | }, | ||
68 | build = { | ||
69 | type = "none" | ||
70 | }, | ||
71 | } | ||
72 | local globals = {} | ||
73 | local quick = true | ||
74 | |||
75 | local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) | ||
76 | |||
77 | assert(rockspec == out) | ||
78 | assert.same(rockspec.build_dependencies, {}) | ||
79 | end) | ||
80 | |||
81 | it("does not add a build dependency for 'module' build type", function() | ||
82 | local filename = "test-1.0-1.rockspec" | ||
83 | local rockspec = { | ||
84 | package = "test", | ||
85 | source = { | ||
86 | url = "", | ||
87 | }, | ||
88 | build = { | ||
89 | type = "none" | ||
90 | }, | ||
91 | } | ||
92 | local globals = {} | ||
93 | local quick = true | ||
94 | |||
95 | local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) | ||
96 | |||
97 | assert(rockspec == out) | ||
98 | assert.same(rockspec.build_dependencies, {}) | ||
99 | end) | ||
100 | |||
101 | for d in lfs.dir(test_env.testing_paths.src_dir .. "/luarocks/build") do | ||
102 | local name = d:match("(.*)%.lua") | ||
103 | if name then | ||
104 | it("does not add a build dependency for vendored '" .. name .. "' type", function() | ||
105 | local filename = "test-1.0-1.rockspec" | ||
106 | local rockspec = { | ||
107 | package = "test", | ||
108 | source = { | ||
109 | url = "", | ||
110 | }, | ||
111 | build = { | ||
112 | type = name | ||
113 | }, | ||
114 | } | ||
115 | local globals = {} | ||
116 | local quick = true | ||
117 | |||
118 | local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) | ||
119 | |||
120 | assert(rockspec == out) | ||
121 | assert.same(rockspec.build_dependencies, {}) | ||
122 | end) | ||
123 | end | ||
124 | end | ||
125 | |||
126 | end) | ||
diff --git a/spec/unit/sysdetect_spec.lua b/spec/unit/sysdetect_spec.lua new file mode 100644 index 00000000..6ec6f6b6 --- /dev/null +++ b/spec/unit/sysdetect_spec.lua | |||
@@ -0,0 +1,75 @@ | |||
1 | |||
2 | local sysdetect = require("luarocks.core.sysdetect") | ||
3 | local lfs = require("lfs") | ||
4 | |||
5 | describe("luarocks.core.sysdetect #unix #unit", function() | ||
6 | |||
7 | setup(function() | ||
8 | os.execute("[ -e binary-samples ] || git clone --depth=1 https://github.com/hishamhm/binary-samples") | ||
9 | os.execute("cd binary-samples && git pull") | ||
10 | end) | ||
11 | |||
12 | local files = { | ||
13 | ["."] = "ignore", | ||
14 | [".."] = "ignore", | ||
15 | ["README.md"] = "ignore", | ||
16 | [".git"] = "ignore", | ||
17 | ["MIT_LICENSE"] = "ignore", | ||
18 | ["anti-disassembler"] = "ignore", | ||
19 | ["elf-Linux-lib-x64.so"] = "ignore", | ||
20 | ["elf-Linux-lib-x86.so"] = "ignore", | ||
21 | |||
22 | ["elf-Linux-x64-bash"] = {"linux", "x86_64"}, | ||
23 | ["elf-Linux-ia64-bash"] = {"linux", "ia_64"}, | ||
24 | ["MachO-OSX-ppc-and-i386-bash"] = {"macosx", "x86"}, | ||
25 | ["MachO-OSX-ppc-openssl-1.0.1h"] = {"macosx", "ppc"}, | ||
26 | ["MachO-iOS-armv7-armv7s-arm64-Helloworld"] = {"macosx", "arm"}, | ||
27 | ["pe-Windows-x64-cmd"] = {"windows", "x86_64"}, | ||
28 | ["MachO-iOS-armv7s-Helloworld"] = {"macosx", "arm"}, | ||
29 | ["elf-Linux-SparcV8-bash"] = {"linux", "sparcv8"}, | ||
30 | ["elf-HPUX-ia64-bash"] = {"hpux", "ia_64"}, | ||
31 | ["MachO-OSX-x64-ls"] = {"macosx", "x86_64"}, | ||
32 | ["pe-Windows-ARMv7-Thumb2LE-HelloWorld"] = {"windows", "armv7l"}, | ||
33 | ["elf-ARMv6-static-gofmt"] = {"sysv", "arm"}, | ||
34 | ["elf-Linux-s390-bash"] = {"linux", "s390"}, | ||
35 | ["elf-Linux-Alpha-bash"] = {"linux", "alpha"}, | ||
36 | ["elf-Linux-hppa-bash"] = {"linux", "hppa"}, | ||
37 | ["elf-Linux-x86_64-static-sln"] = {"linux", "x86_64"}, | ||
38 | ["elf-Linux-Mips4-bash"] = {"linux", "mips"}, | ||
39 | ["elf-ARMv6-dynamic-go"] = {"linux", "arm"}, | ||
40 | ["elf-Linux-SuperH4-bash"] = {"linux", "superh"}, | ||
41 | ["elf-Linux-x86-bash"] = {"linux", "x86"}, | ||
42 | ["elf-Linux-PowerPC-bash"] = {"linux", "ppc"}, | ||
43 | ["libSystem.B.dylib"] = {"macosx", "x86_64"}, | ||
44 | ["MachO-iOS-arm1176JZFS-bash"] = {"macosx", "arm"}, | ||
45 | ["pe-Windows-x86-cmd"] = {"windows", "x86"}, | ||
46 | ["elf-Linux-ARMv7-ls"] = {"linux", "arm"}, | ||
47 | ["elf-Linux-ARM64-bash"] = {"linux", "aarch64"}, | ||
48 | ["MachO-OSX-x86-ls"] = {"macosx", "x86"}, | ||
49 | ["elf-solaris-sparc-ls"] = {"solaris", "sparc"}, | ||
50 | ["elf-solaris-x86-ls"] = {"solaris", "x86"}, | ||
51 | ["pe-mingw32-strip.exe"] = {"windows", "x86"}, | ||
52 | ["elf-OpenBSD-x86_64-sh"] = {"openbsd", "x86_64"}, | ||
53 | ["elf-NetBSD-x86_64-echo"] = {"netbsd", "x86_64"}, | ||
54 | ["elf-FreeBSD-x86_64-echo"] = {"freebsd", "x86_64"}, | ||
55 | ["elf-Haiku-GCC2-ls"] = {"haiku", "x86"}, | ||
56 | ["elf-Haiku-GCC7-WebPositive"] = {"haiku", "x86"}, | ||
57 | ["pe-cygwin-ls.exe"] = {"cygwin", "x86"}, | ||
58 | ["elf-DragonFly-x86_64-less"] = {"dragonfly", "x86_64"}, | ||
59 | |||
60 | } | ||
61 | |||
62 | describe("detect_file", function() | ||
63 | it("detects system and processor", function() | ||
64 | for f in lfs.dir("binary-samples") do | ||
65 | if files[f] ~= "ignore" then | ||
66 | assert.table(files[f], "unknown binary " .. f) | ||
67 | local expected_s, expected_p = files[f][1], files[f][2] | ||
68 | local s, p = sysdetect.detect_file("binary-samples/" .. f) | ||
69 | assert.same(expected_s, s, "bad system for " .. f) | ||
70 | assert.same(expected_p, p, "bad processor for " .. f) | ||
71 | end | ||
72 | end | ||
73 | end) | ||
74 | end) | ||
75 | end) | ||
diff --git a/spec/unit/tools_spec.lua b/spec/unit/tools_spec.lua new file mode 100644 index 00000000..29e21740 --- /dev/null +++ b/spec/unit/tools_spec.lua | |||
@@ -0,0 +1,253 @@ | |||
1 | local test_env = require("spec.util.test_env") | ||
2 | local get_tmp_path = test_env.get_tmp_path | ||
3 | local testing_paths = test_env.testing_paths | ||
4 | local write_file = test_env.write_file | ||
5 | |||
6 | test_env.unload_luarocks() | ||
7 | local fs = require("luarocks.fs") | ||
8 | local cfg = require("luarocks.core.cfg") | ||
9 | local patch = require("luarocks.tools.patch") | ||
10 | |||
11 | local lao = | ||
12 | [[The Nameless is the origin of Heaven and Earth; | ||
13 | The named is the mother of all things. | ||
14 | |||
15 | Therefore let there always be non-being, | ||
16 | so we may see their subtlety, | ||
17 | And let there always be being, | ||
18 | so we may see their outcome. | ||
19 | The two are the same, | ||
20 | But after they are produced, | ||
21 | they have different names. | ||
22 | They both may be called deep and profound. | ||
23 | Deeper and more profound, | ||
24 | The door of all subtleties!]] | ||
25 | |||
26 | local tzu = | ||
27 | [[The Way that can be told of is not the eternal Way; | ||
28 | The name that can be named is not the eternal name. | ||
29 | The Nameless is the origin of Heaven and Earth; | ||
30 | The Named is the mother of all things. | ||
31 | Therefore let there always be non-being, | ||
32 | so we may see their subtlety, | ||
33 | And let there always be being, | ||
34 | so we may see their outcome. | ||
35 | The two are the same, | ||
36 | But after they are produced, | ||
37 | they have different names.]] | ||
38 | |||
39 | local valid_patch1 = | ||
40 | [[--- lao 2002-02-21 23:30:39.942229878 -0800 | ||
41 | +++ tzu 2002-02-21 23:30:50.442260588 -0800 | ||
42 | @@ -1,7 +1,6 @@ | ||
43 | -The Way that can be told of is not the eternal Way; | ||
44 | -The name that can be named is not the eternal name. | ||
45 | The Nameless is the origin of Heaven and Earth; | ||
46 | -The Named is the mother of all things. | ||
47 | +The named is the mother of all things. | ||
48 | + | ||
49 | Therefore let there always be non-being, | ||
50 | so we may see their subtlety, | ||
51 | And let there always be being, | ||
52 | @@ -9,3 +8,6 @@ | ||
53 | The two are the same, | ||
54 | But after they are produced, | ||
55 | they have different names. | ||
56 | +They both may be called deep and profound. | ||
57 | +Deeper and more profound, | ||
58 | +The door of all subtleties!]] | ||
59 | |||
60 | local valid_patch2 = | ||
61 | [[--- /dev/null 1969-02-21 23:30:39.942229878 -0800 | ||
62 | +++ tzu 2002-02-21 23:30:50.442260588 -0800 | ||
63 | @@ -1,7 +1,6 @@ | ||
64 | -The Way that can be told of is not the eternal Way; | ||
65 | -The name that can be named is not the eternal name. | ||
66 | The Nameless is the origin of Heaven and Earth; | ||
67 | -The Named is the mother of all things. | ||
68 | +The named is the mother of all things. | ||
69 | + | ||
70 | Therefore let there always be non-being, | ||
71 | so we may see their subtlety, | ||
72 | And let there always be being, | ||
73 | @@ -9,3 +8,6 @@ | ||
74 | The two are the same, | ||
75 | But after they are produced, | ||
76 | they have different names. | ||
77 | +They both may be called deep and profound. | ||
78 | +Deeper and more profound, | ||
79 | +The door of all subtleties!]] | ||
80 | |||
81 | local invalid_patch1 = | ||
82 | [[--- lao 2002-02-21 23:30:39.942229878 -0800 | ||
83 | +++ tzu 2002-02-21 23:30:50.442260588 -0800 | ||
84 | @@ -1,7 +1,6 @@ | ||
85 | -The Way that can be told of is not the eternal Way; | ||
86 | -The name that can be named is not the eternal name. | ||
87 | The Nameless is the origin of Heaven and Earth; | ||
88 | -The Named is the mother of all things. | ||
89 | --- Extra | ||
90 | +The named is the mother of all things. | ||
91 | + | ||
92 | Therefore let there always be non-being, | ||
93 | so we may see their subtlety, | ||
94 | And let there always be being, | ||
95 | --- Extra | ||
96 | @@ -9,3 +8,7 @@ | ||
97 | The two are the same, | ||
98 | But after they are produced, | ||
99 | they have different names. | ||
100 | +They both may be called deep and profound. | ||
101 | +Deeper and more profound, | ||
102 | +The door of all subtleties!]] | ||
103 | |||
104 | local invalid_patch2 = | ||
105 | [[--- lao 2002-02-21 23:30:39.942229878 -0800 | ||
106 | +++ tzu 2002-02-21 23:30:50.442260588 -0800 | ||
107 | @@ -1,7 +1,6 @@ | ||
108 | -The Way that can be told of is not the eternal Way; | ||
109 | -The name that can be named is not the eternal name. | ||
110 | The Nameless is the origin of Heaven and Earth; | ||
111 | -The Named is the mother of all things. | ||
112 | +The named is the mother of all things. | ||
113 | + | ||
114 | Therefore let there always be non-being, | ||
115 | so we may see their subtlety, | ||
116 | And let there always be being, | ||
117 | @@ -9,3 +8,6 @@ | ||
118 | The two are the same, | ||
119 | But after they are produced, | ||
120 | they have different names. | ||
121 | +They both may be called deep and profound. | ||
122 | +Deeper and more profound, | ||
123 | ? ... | ||
124 | +The door of all subtleties!]] | ||
125 | |||
126 | local invalid_patch3 = | ||
127 | [[--- lao 2002-02-21 23:30:39.942229878 -0800 | ||
128 | +++ tzu 2002-02-21 23:30:50.442260588 -0800 | ||
129 | @@ -1,7 +1,6 @@ | ||
130 | -The Way that can be told of is not the eternal Way; | ||
131 | -The name that can be named is not the eternal name. | ||
132 | The Nameless is the origin of Heaven and Earth; | ||
133 | -The Named is the mother of all things. | ||
134 | +The named is the mother of all things. | ||
135 | + | ||
136 | Therefore let there always be non-being, | ||
137 | so we may see their subtlety, | ||
138 | And let there always be being, | ||
139 | @@ -9,3 +8,6 @@ | ||
140 | The two are the same, | ||
141 | But after they are produced, | ||
142 | they have different names. | ||
143 | +They both may be called deep and profound. | ||
144 | +Deeper and more profound, | ||
145 | ? ... | ||
146 | +The door of all subtleties!]] | ||
147 | |||
148 | describe("Luarocks patch test #unit", function() | ||
149 | local runner | ||
150 | |||
151 | setup(function() | ||
152 | cfg.init() | ||
153 | fs.init() | ||
154 | runner = require("luacov.runner") | ||
155 | runner.init(testing_paths.testrun_dir .. "/luacov.config") | ||
156 | runner.tick = true | ||
157 | end) | ||
158 | |||
159 | teardown(function() | ||
160 | runner.shutdown() | ||
161 | end) | ||
162 | |||
163 | describe("patch.read_patch", function() | ||
164 | it("returns a table with the patch file info and the result of parsing the file", function() | ||
165 | local t, result | ||
166 | |||
167 | write_file("test.patch", valid_patch1, finally) | ||
168 | t, result = patch.read_patch("test.patch") | ||
169 | assert.truthy(result) | ||
170 | assert.truthy(t) | ||
171 | |||
172 | write_file("test.patch", invalid_patch1, finally) | ||
173 | t, result = patch.read_patch("test.patch") | ||
174 | assert.falsy(result) | ||
175 | assert.truthy(t) | ||
176 | |||
177 | write_file("test.patch", invalid_patch2, finally) | ||
178 | t, result = patch.read_patch("test.patch") | ||
179 | assert.falsy(result) | ||
180 | assert.truthy(t) | ||
181 | |||
182 | write_file("test.patch", invalid_patch3, finally) | ||
183 | t, result = patch.read_patch("test.patch") | ||
184 | assert.falsy(result) | ||
185 | assert.truthy(t) | ||
186 | end) | ||
187 | end) | ||
188 | |||
189 | describe("patch.apply_patch", function() | ||
190 | local tmpdir | ||
191 | local olddir | ||
192 | |||
193 | before_each(function() | ||
194 | tmpdir = get_tmp_path() | ||
195 | olddir = lfs.currentdir() | ||
196 | lfs.mkdir(tmpdir) | ||
197 | lfs.chdir(tmpdir) | ||
198 | |||
199 | write_file("lao", tzu, finally) | ||
200 | write_file("tzu", lao, finally) | ||
201 | end) | ||
202 | |||
203 | after_each(function() | ||
204 | if olddir then | ||
205 | lfs.chdir(olddir) | ||
206 | if tmpdir then | ||
207 | lfs.rmdir(tmpdir) | ||
208 | end | ||
209 | end | ||
210 | end) | ||
211 | |||
212 | it("applies the given patch and returns the result of patching", function() | ||
213 | write_file("test.patch", valid_patch1, finally) | ||
214 | local p = patch.read_patch("test.patch") | ||
215 | local result = patch.apply_patch(p) | ||
216 | assert.truthy(result) | ||
217 | end) | ||
218 | |||
219 | it("applies the given patch with custom arguments and returns the result of patching", function() | ||
220 | write_file("test.patch", valid_patch2, finally) | ||
221 | local p = patch.read_patch("test.patch") | ||
222 | local result = patch.apply_patch(p, nil, true) | ||
223 | assert.truthy(result) | ||
224 | end) | ||
225 | |||
226 | it("fails if the patch file is invalid", function() | ||
227 | write_file("test.patch", invalid_patch1, finally) | ||
228 | local p = patch.read_patch("test.patch") | ||
229 | local result = pcall(patch.apply_patch, p) | ||
230 | assert.falsy(result) | ||
231 | end) | ||
232 | |||
233 | it("returns false if the files from the patch doesn't exist", function() | ||
234 | os.remove("lao") | ||
235 | os.remove("tzu") | ||
236 | |||
237 | write_file("test.patch", valid_patch1, finally) | ||
238 | local p = patch.read_patch("test.patch") | ||
239 | local result = patch.apply_patch(p) | ||
240 | assert.falsy(result) | ||
241 | end) | ||
242 | |||
243 | it("returns false if the target file was already patched", function() | ||
244 | write_file("test.patch", valid_patch1, finally) | ||
245 | local p = patch.read_patch("test.patch") | ||
246 | local result = patch.apply_patch(p) | ||
247 | assert.truthy(result) | ||
248 | |||
249 | result = patch.apply_patch(p) | ||
250 | assert.falsy(result) | ||
251 | end) | ||
252 | end) | ||
253 | end) | ||