aboutsummaryrefslogtreecommitdiff
path: root/spec/unit
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2024-02-26 17:47:28 -0300
committerHisham Muhammad <hisham@gobolinux.org>2024-02-27 13:28:33 -0300
commit5cba4b83f60966045b86ac615df2692c953ebba7 (patch)
tree445d1f58e589b53e4ee8cda5984f430f54fd2b36 /spec/unit
parent6bc6ede826843c3692971c14c27c3d27714b2126 (diff)
downloadluarocks-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.lua369
-rw-r--r--spec/unit/dir_spec.lua72
-rw-r--r--spec/unit/fetch_spec.lua488
-rw-r--r--spec/unit/fs_spec.lua1607
-rw-r--r--spec/unit/fun_spec.lua130
-rw-r--r--spec/unit/persist_spec.lua76
-rw-r--r--spec/unit/rockspecs_spec.lua126
-rw-r--r--spec/unit/sysdetect_spec.lua75
-rw-r--r--spec/unit/tools_spec.lua253
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 @@
1local test_env = require("spec.util.test_env")
2local lfs = require("lfs")
3local get_tmp_path = test_env.get_tmp_path
4local run = test_env.run
5local testing_paths = test_env.testing_paths
6local write_file = test_env.write_file
7local P = test_env.P
8
9test_env.unload_luarocks()
10
11test_env.unload_luarocks()
12test_env.setup_specs()
13local cfg = require("luarocks.core.cfg")
14local deps = require("luarocks.deps")
15local fs = require("luarocks.fs")
16local path = require("luarocks.path")
17local rockspecs = require("luarocks.rockspecs")
18local build_builtin = require("luarocks.build.builtin")
19
20local 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
32describe("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)
369end)
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 @@
1local test_env = require("spec.util.test_env")
2local testing_paths = test_env.testing_paths
3local P = test_env.P
4
5test_env.unload_luarocks()
6test_env.setup_specs()
7local dir = require("luarocks.dir")
8
9describe("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
72end)
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 @@
1local test_env = require("spec.util.test_env")
2
3test_env.unload_luarocks()
4test_env.setup_specs()
5local cfg = require("luarocks.core.cfg")
6local fetch = require("luarocks.fetch")
7local fs = require("luarocks.fs")
8local dir = require("luarocks.dir")
9local path = require("luarocks.path")
10local rockspecs = require("luarocks.rockspecs")
11local lfs = require("lfs")
12local get_tmp_path = test_env.get_tmp_path
13local testing_paths = test_env.testing_paths
14local write_file = test_env.write_file
15local P = test_env.P
16
17describe("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
488end)
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 @@
1local test_env = require("spec.util.test_env")
2
3test_env.unload_luarocks()
4test_env.setup_specs()
5local fs = require("luarocks.fs")
6local path = require("luarocks.path")
7local cfg = require("luarocks.core.cfg")
8local lfs = require("lfs")
9local is_win = test_env.TEST_TARGET_OS == "windows"
10local posix_ok = pcall(require, "posix")
11local testing_paths = test_env.testing_paths
12local get_tmp_path = test_env.get_tmp_path
13local write_file = test_env.write_file
14local 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
18local function chdir(d)
19 lfs.chdir(d)
20 fs.change_dir(d)
21end
22
23describe("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
1607end)
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 @@
1local test_env = require("spec.util.test_env")
2local testing_paths = test_env.testing_paths
3
4test_env.unload_luarocks()
5local fun = require("luarocks.fun")
6
7describe("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)
130end)
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 @@
1local test_env = require("spec.util.test_env")
2local testing_paths = test_env.testing_paths
3
4test_env.unload_luarocks()
5local persist = require("luarocks.persist")
6
7describe("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([[
23bar = 1234
24foo = "string"
25]], persist.save_from_table_to_string({foo = "string", bar = 1234}))
26 end)
27
28 it("nested tables", function()
29 assert.are.same([[
30bar = {
31 baz = "string"
32}
33foo = {
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([[
41bar = {
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([[
49bar = "a \\backslash?"
50foo = "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([===[
56bar = [==[
57]]
58]=]]==]
59foo = [[
60First line
61Second 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([===[
67bar = [==[
68]]
69]=]==]
70foo = [=[
71First line
72Second line [1]]=]
73]===], persist.save_from_table_to_string({foo = "First line\nSecond line [1]", bar = "]]\n]="}))
74 end)
75 end)
76end)
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
2local rockspecs = require("luarocks.rockspecs")
3local cfg = require("luarocks.core.cfg")
4local test_env = require("spec.util.test_env")
5local lfs = require("lfs")
6
7describe("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
126end)
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
2local sysdetect = require("luarocks.core.sysdetect")
3local lfs = require("lfs")
4
5describe("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)
75end)
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 @@
1local test_env = require("spec.util.test_env")
2local get_tmp_path = test_env.get_tmp_path
3local testing_paths = test_env.testing_paths
4local write_file = test_env.write_file
5
6test_env.unload_luarocks()
7local fs = require("luarocks.fs")
8local cfg = require("luarocks.core.cfg")
9local patch = require("luarocks.tools.patch")
10
11local lao =
12[[The Nameless is the origin of Heaven and Earth;
13The named is the mother of all things.
14
15Therefore let there always be non-being,
16 so we may see their subtlety,
17And let there always be being,
18 so we may see their outcome.
19The two are the same,
20But after they are produced,
21 they have different names.
22They both may be called deep and profound.
23Deeper and more profound,
24The door of all subtleties!]]
25
26local tzu =
27[[The Way that can be told of is not the eternal Way;
28The name that can be named is not the eternal name.
29The Nameless is the origin of Heaven and Earth;
30The Named is the mother of all things.
31Therefore let there always be non-being,
32 so we may see their subtlety,
33And let there always be being,
34 so we may see their outcome.
35The two are the same,
36But after they are produced,
37 they have different names.]]
38
39local 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
60local 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
81local 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
104local 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
126local 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
148describe("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)
253end)