1// Copyright 2011 The Kyua Authors.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9//   notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright
11//   notice, this list of conditions and the following disclaimer in the
12//   documentation and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors
14//   may be used to endorse or promote products derived from this software
15//   without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "utils/fs/lua_module.hpp"
30
31#include <atf-c++.hpp>
32#include <lutok/operations.hpp>
33#include <lutok/state.hpp>
34#include <lutok/test_utils.hpp>
35
36#include "utils/format/macros.hpp"
37#include "utils/fs/operations.hpp"
38#include "utils/fs/path.hpp"
39
40namespace fs = utils::fs;
41
42
43ATF_TEST_CASE_WITHOUT_HEAD(open_fs);
44ATF_TEST_CASE_BODY(open_fs)
45{
46    lutok::state state;
47    stack_balance_checker checker(state);
48    fs::open_fs(state);
49    lutok::do_string(state, "return fs.basename", 0, 1, 0);
50    ATF_REQUIRE(state.is_function(-1));
51    lutok::do_string(state, "return fs.dirname", 0, 1, 0);
52    ATF_REQUIRE(state.is_function(-1));
53    lutok::do_string(state, "return fs.join", 0, 1, 0);
54    ATF_REQUIRE(state.is_function(-1));
55    state.pop(3);
56}
57
58
59ATF_TEST_CASE_WITHOUT_HEAD(basename__ok);
60ATF_TEST_CASE_BODY(basename__ok)
61{
62    lutok::state state;
63    fs::open_fs(state);
64
65    lutok::do_string(state, "return fs.basename('/my/test//file_foobar')",
66                     0, 1, 0);
67    ATF_REQUIRE_EQ("file_foobar", state.to_string(-1));
68    state.pop(1);
69}
70
71
72ATF_TEST_CASE_WITHOUT_HEAD(basename__fail);
73ATF_TEST_CASE_BODY(basename__fail)
74{
75    lutok::state state;
76    fs::open_fs(state);
77
78    ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
79                         lutok::do_string(state, "return fs.basename({})",
80                                          0, 1, 0));
81    ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
82                         lutok::do_string(state, "return fs.basename('')",
83                                          0, 1, 0));
84}
85
86
87ATF_TEST_CASE_WITHOUT_HEAD(dirname__ok);
88ATF_TEST_CASE_BODY(dirname__ok)
89{
90    lutok::state state;
91    fs::open_fs(state);
92
93    lutok::do_string(state, "return fs.dirname('/my/test//file_foobar')",
94                     0, 1, 0);
95    ATF_REQUIRE_EQ("/my/test", state.to_string(-1));
96    state.pop(1);
97}
98
99
100ATF_TEST_CASE_WITHOUT_HEAD(dirname__fail);
101ATF_TEST_CASE_BODY(dirname__fail)
102{
103    lutok::state state;
104    fs::open_fs(state);
105
106    ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
107                         lutok::do_string(state, "return fs.dirname({})",
108                                          0, 1, 0));
109    ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
110                         lutok::do_string(state, "return fs.dirname('')",
111                                          0, 1, 0));
112}
113
114
115ATF_TEST_CASE_WITHOUT_HEAD(exists__ok);
116ATF_TEST_CASE_BODY(exists__ok)
117{
118    lutok::state state;
119    fs::open_fs(state);
120
121    atf::utils::create_file("foo", "");
122
123    lutok::do_string(state, "return fs.exists('foo')", 0, 1, 0);
124    ATF_REQUIRE(state.to_boolean(-1));
125    state.pop(1);
126
127    lutok::do_string(state, "return fs.exists('bar')", 0, 1, 0);
128    ATF_REQUIRE(!state.to_boolean(-1));
129    state.pop(1);
130
131    lutok::do_string(state,
132                     F("return fs.exists('%s')") % fs::current_path(), 0, 1, 0);
133    ATF_REQUIRE(state.to_boolean(-1));
134    state.pop(1);
135}
136
137
138ATF_TEST_CASE_WITHOUT_HEAD(exists__fail);
139ATF_TEST_CASE_BODY(exists__fail)
140{
141    lutok::state state;
142    fs::open_fs(state);
143
144    ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
145                         lutok::do_string(state, "return fs.exists({})",
146                                          0, 1, 0));
147    ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
148                         lutok::do_string(state, "return fs.exists('')",
149                                          0, 1, 0));
150}
151
152
153ATF_TEST_CASE_WITHOUT_HEAD(exists__custom_start_dir);
154ATF_TEST_CASE_BODY(exists__custom_start_dir)
155{
156    lutok::state state;
157    fs::open_fs(state, fs::path("subdir"));
158
159    fs::mkdir(fs::path("subdir"), 0755);
160    atf::utils::create_file("subdir/foo", "");
161    atf::utils::create_file("bar", "");
162
163    lutok::do_string(state, "return fs.exists('foo')", 0, 1, 0);
164    ATF_REQUIRE(state.to_boolean(-1));
165    state.pop(1);
166
167    lutok::do_string(state, "return fs.exists('subdir/foo')", 0, 1, 0);
168    ATF_REQUIRE(!state.to_boolean(-1));
169    state.pop(1);
170
171    lutok::do_string(state, "return fs.exists('bar')", 0, 1, 0);
172    ATF_REQUIRE(!state.to_boolean(-1));
173    state.pop(1);
174
175    lutok::do_string(state, "return fs.exists('../bar')", 0, 1, 0);
176    ATF_REQUIRE(state.to_boolean(-1));
177    state.pop(1);
178
179    lutok::do_string(state,
180                     F("return fs.exists('%s')") % (fs::current_path() / "bar"),
181                     0, 1, 0);
182    ATF_REQUIRE(state.to_boolean(-1));
183    state.pop(1);
184}
185
186
187ATF_TEST_CASE_WITHOUT_HEAD(files__none);
188ATF_TEST_CASE_BODY(files__none)
189{
190    lutok::state state;
191    state.open_table();
192    fs::open_fs(state);
193
194    fs::mkdir(fs::path("root"), 0755);
195
196    lutok::do_string(state,
197                     "names = {}\n"
198                     "for file in fs.files('root') do\n"
199                     "    table.insert(names, file)\n"
200                     "end\n"
201                     "table.sort(names)\n"
202                     "return table.concat(names, ' ')",
203                     0, 1, 0);
204    ATF_REQUIRE_EQ(". ..", state.to_string(-1));
205    state.pop(1);
206}
207
208
209ATF_TEST_CASE_WITHOUT_HEAD(files__some);
210ATF_TEST_CASE_BODY(files__some)
211{
212    lutok::state state;
213    state.open_table();
214    fs::open_fs(state);
215
216    fs::mkdir(fs::path("root"), 0755);
217    atf::utils::create_file("root/file1", "");
218    atf::utils::create_file("root/file2", "");
219
220    lutok::do_string(state,
221                     "names = {}\n"
222                     "for file in fs.files('root') do\n"
223                     "    table.insert(names, file)\n"
224                     "end\n"
225                     "table.sort(names)\n"
226                     "return table.concat(names, ' ')",
227                     0, 1, 0);
228    ATF_REQUIRE_EQ(". .. file1 file2", state.to_string(-1));
229    state.pop(1);
230}
231
232
233ATF_TEST_CASE_WITHOUT_HEAD(files__some_with_custom_start_dir);
234ATF_TEST_CASE_BODY(files__some_with_custom_start_dir)
235{
236    lutok::state state;
237    state.open_table();
238    fs::open_fs(state, fs::current_path() / "root");
239
240    fs::mkdir(fs::path("root"), 0755);
241    atf::utils::create_file("root/file1", "");
242    atf::utils::create_file("root/file2", "");
243    atf::utils::create_file("file3", "");
244
245    lutok::do_string(state,
246                     "names = {}\n"
247                     "for file in fs.files('.') do\n"
248                     "    table.insert(names, file)\n"
249                     "end\n"
250                     "table.sort(names)\n"
251                     "return table.concat(names, ' ')",
252                     0, 1, 0);
253    ATF_REQUIRE_EQ(". .. file1 file2", state.to_string(-1));
254    state.pop(1);
255}
256
257
258ATF_TEST_CASE_WITHOUT_HEAD(files__fail_arg);
259ATF_TEST_CASE_BODY(files__fail_arg)
260{
261    lutok::state state;
262    fs::open_fs(state);
263
264    ATF_REQUIRE_THROW_RE(lutok::error, "Need a string parameter",
265                         lutok::do_string(state, "fs.files({})", 0, 0, 0));
266    ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
267                         lutok::do_string(state, "fs.files('')", 0, 0, 0));
268}
269
270
271ATF_TEST_CASE_WITHOUT_HEAD(files__fail_opendir);
272ATF_TEST_CASE_BODY(files__fail_opendir)
273{
274    lutok::state state;
275    fs::open_fs(state);
276
277    ATF_REQUIRE_THROW_RE(lutok::error, "Failed to open directory",
278                         lutok::do_string(state, "fs.files('root')", 0, 0, 0));
279}
280
281
282ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__ok);
283ATF_TEST_CASE_BODY(is_absolute__ok)
284{
285    lutok::state state;
286    fs::open_fs(state);
287
288    lutok::do_string(state, "return fs.is_absolute('my/test//file_foobar')",
289                     0, 1, 0);
290    ATF_REQUIRE(!state.to_boolean(-1));
291    lutok::do_string(state, "return fs.is_absolute('/my/test//file_foobar')",
292                     0, 1, 0);
293    ATF_REQUIRE(state.to_boolean(-1));
294    state.pop(2);
295}
296
297
298ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__fail);
299ATF_TEST_CASE_BODY(is_absolute__fail)
300{
301    lutok::state state;
302    fs::open_fs(state);
303
304    ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
305                         lutok::do_string(state, "return fs.is_absolute({})",
306                                          0, 1, 0));
307    ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
308                         lutok::do_string(state, "return fs.is_absolute('')",
309                                          0, 1, 0));
310}
311
312
313ATF_TEST_CASE_WITHOUT_HEAD(join__ok);
314ATF_TEST_CASE_BODY(join__ok)
315{
316    lutok::state state;
317    fs::open_fs(state);
318
319    lutok::do_string(state, "return fs.join('/a/b///', 'c/d')", 0, 1, 0);
320    ATF_REQUIRE_EQ("/a/b/c/d", state.to_string(-1));
321    state.pop(1);
322}
323
324
325ATF_TEST_CASE_WITHOUT_HEAD(join__fail);
326ATF_TEST_CASE_BODY(join__fail)
327{
328    lutok::state state;
329    fs::open_fs(state);
330
331    ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
332                         lutok::do_string(state, "return fs.join({}, 'a')",
333                                          0, 1, 0));
334    ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
335                         lutok::do_string(state, "return fs.join('a', {})",
336                                          0, 1, 0));
337
338    ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
339                         lutok::do_string(state, "return fs.join('', 'a')",
340                                          0, 1, 0));
341    ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
342                         lutok::do_string(state, "return fs.join('a', '')",
343                                          0, 1, 0));
344
345    ATF_REQUIRE_THROW_RE(lutok::error, "Cannot join.*'a/b'.*'/c'",
346                         lutok::do_string(state, "fs.join('a/b', '/c')",
347                                          0, 0, 0));
348}
349
350
351ATF_INIT_TEST_CASES(tcs)
352{
353    ATF_ADD_TEST_CASE(tcs, open_fs);
354
355    ATF_ADD_TEST_CASE(tcs, basename__ok);
356    ATF_ADD_TEST_CASE(tcs, basename__fail);
357
358    ATF_ADD_TEST_CASE(tcs, dirname__ok);
359    ATF_ADD_TEST_CASE(tcs, dirname__fail);
360
361    ATF_ADD_TEST_CASE(tcs, exists__ok);
362    ATF_ADD_TEST_CASE(tcs, exists__fail);
363    ATF_ADD_TEST_CASE(tcs, exists__custom_start_dir);
364
365    ATF_ADD_TEST_CASE(tcs, files__none);
366    ATF_ADD_TEST_CASE(tcs, files__some);
367    ATF_ADD_TEST_CASE(tcs, files__some_with_custom_start_dir);
368    ATF_ADD_TEST_CASE(tcs, files__fail_arg);
369    ATF_ADD_TEST_CASE(tcs, files__fail_opendir);
370
371    ATF_ADD_TEST_CASE(tcs, is_absolute__ok);
372    ATF_ADD_TEST_CASE(tcs, is_absolute__fail);
373
374    ATF_ADD_TEST_CASE(tcs, join__ok);
375    ATF_ADD_TEST_CASE(tcs, join__fail);
376}
377