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 
40 namespace fs = utils::fs;
41 
42 
43 ATF_TEST_CASE_WITHOUT_HEAD(open_fs);
ATF_TEST_CASE_BODY(open_fs)44 ATF_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 
59 ATF_TEST_CASE_WITHOUT_HEAD(basename__ok);
ATF_TEST_CASE_BODY(basename__ok)60 ATF_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 
72 ATF_TEST_CASE_WITHOUT_HEAD(basename__fail);
ATF_TEST_CASE_BODY(basename__fail)73 ATF_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 
87 ATF_TEST_CASE_WITHOUT_HEAD(dirname__ok);
ATF_TEST_CASE_BODY(dirname__ok)88 ATF_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 
100 ATF_TEST_CASE_WITHOUT_HEAD(dirname__fail);
ATF_TEST_CASE_BODY(dirname__fail)101 ATF_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 
115 ATF_TEST_CASE_WITHOUT_HEAD(exists__ok);
ATF_TEST_CASE_BODY(exists__ok)116 ATF_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 
138 ATF_TEST_CASE_WITHOUT_HEAD(exists__fail);
ATF_TEST_CASE_BODY(exists__fail)139 ATF_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 
153 ATF_TEST_CASE_WITHOUT_HEAD(exists__custom_start_dir);
ATF_TEST_CASE_BODY(exists__custom_start_dir)154 ATF_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 
187 ATF_TEST_CASE_WITHOUT_HEAD(files__none);
ATF_TEST_CASE_BODY(files__none)188 ATF_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 
209 ATF_TEST_CASE_WITHOUT_HEAD(files__some);
ATF_TEST_CASE_BODY(files__some)210 ATF_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 
233 ATF_TEST_CASE_WITHOUT_HEAD(files__some_with_custom_start_dir);
ATF_TEST_CASE_BODY(files__some_with_custom_start_dir)234 ATF_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 
258 ATF_TEST_CASE_WITHOUT_HEAD(files__fail_arg);
ATF_TEST_CASE_BODY(files__fail_arg)259 ATF_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 
271 ATF_TEST_CASE_WITHOUT_HEAD(files__fail_opendir);
ATF_TEST_CASE_BODY(files__fail_opendir)272 ATF_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 
282 ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__ok);
ATF_TEST_CASE_BODY(is_absolute__ok)283 ATF_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 
298 ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__fail);
ATF_TEST_CASE_BODY(is_absolute__fail)299 ATF_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 
313 ATF_TEST_CASE_WITHOUT_HEAD(join__ok);
ATF_TEST_CASE_BODY(join__ok)314 ATF_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 
325 ATF_TEST_CASE_WITHOUT_HEAD(join__fail);
ATF_TEST_CASE_BODY(join__fail)326 ATF_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 
ATF_INIT_TEST_CASES(tcs)351 ATF_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