1 // Copyright 2011 Google Inc.
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/fs/operations.hpp"
37 #include "utils/fs/path.hpp"
38 
39 namespace fs = utils::fs;
40 
41 
42 ATF_TEST_CASE_WITHOUT_HEAD(open_fs);
43 ATF_TEST_CASE_BODY(open_fs)
44 {
45     lutok::state state;
46     stack_balance_checker checker(state);
47     fs::open_fs(state);
48     lutok::do_string(state, "return fs.basename", 1);
49     ATF_REQUIRE(state.is_function());
50     lutok::do_string(state, "return fs.dirname", 1);
51     ATF_REQUIRE(state.is_function());
52     lutok::do_string(state, "return fs.join", 1);
53     ATF_REQUIRE(state.is_function());
54     state.pop(3);
55 }
56 
57 
58 ATF_TEST_CASE_WITHOUT_HEAD(basename__ok);
59 ATF_TEST_CASE_BODY(basename__ok)
60 {
61     lutok::state state;
62     fs::open_fs(state);
63 
64     lutok::do_string(state, "return fs.basename('/my/test//file_foobar')", 1);
65     ATF_REQUIRE_EQ("file_foobar", state.to_string());
66     state.pop(1);
67 }
68 
69 
70 ATF_TEST_CASE_WITHOUT_HEAD(basename__fail);
71 ATF_TEST_CASE_BODY(basename__fail)
72 {
73     lutok::state state;
74     fs::open_fs(state);
75 
76     ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
77                          lutok::do_string(state, "return fs.basename({})", 1));
78     ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
79                          lutok::do_string(state, "return fs.basename('')", 1));
80 }
81 
82 
83 ATF_TEST_CASE_WITHOUT_HEAD(dirname__ok);
84 ATF_TEST_CASE_BODY(dirname__ok)
85 {
86     lutok::state state;
87     fs::open_fs(state);
88 
89     lutok::do_string(state, "return fs.dirname('/my/test//file_foobar')", 1);
90     ATF_REQUIRE_EQ("/my/test", state.to_string());
91     state.pop(1);
92 }
93 
94 
95 ATF_TEST_CASE_WITHOUT_HEAD(dirname__fail);
96 ATF_TEST_CASE_BODY(dirname__fail)
97 {
98     lutok::state state;
99     fs::open_fs(state);
100 
101     ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
102                          lutok::do_string(state, "return fs.dirname({})", 1));
103     ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
104                          lutok::do_string(state, "return fs.dirname('')", 1));
105 }
106 
107 
108 ATF_TEST_CASE_WITHOUT_HEAD(exists__ok);
109 ATF_TEST_CASE_BODY(exists__ok)
110 {
111     lutok::state state;
112     fs::open_fs(state);
113 
114     atf::utils::create_file("foo", "");
115 
116     lutok::do_string(state, "return fs.exists('foo')", 1);
117     ATF_REQUIRE(state.to_boolean());
118     state.pop(1);
119 
120     lutok::do_string(state, "return fs.exists('bar')", 1);
121     ATF_REQUIRE(!state.to_boolean());
122     state.pop(1);
123 }
124 
125 
126 ATF_TEST_CASE_WITHOUT_HEAD(exists__fail);
127 ATF_TEST_CASE_BODY(exists__fail)
128 {
129     lutok::state state;
130     fs::open_fs(state);
131 
132     ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
133                          lutok::do_string(state, "return fs.exists({})", 1));
134     ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
135                          lutok::do_string(state, "return fs.exists('')", 1));
136 }
137 
138 
139 ATF_TEST_CASE_WITHOUT_HEAD(files__none);
140 ATF_TEST_CASE_BODY(files__none)
141 {
142     lutok::state state;
143     state.open_table();
144     fs::open_fs(state);
145 
146     fs::mkdir(fs::path("root"), 0755);
147 
148     lutok::do_string(state,
149                      "names = {}\n"
150                      "for file in fs.files('root') do\n"
151                      "    table.insert(names, file)\n"
152                      "end\n"
153                      "table.sort(names)\n"
154                      "return table.concat(names, ' ')", 1);
155     ATF_REQUIRE_EQ(". ..", state.to_string());
156     state.pop(1);
157 }
158 
159 
160 ATF_TEST_CASE_WITHOUT_HEAD(files__some);
161 ATF_TEST_CASE_BODY(files__some)
162 {
163     lutok::state state;
164     state.open_table();
165     fs::open_fs(state);
166 
167     fs::mkdir(fs::path("root"), 0755);
168     atf::utils::create_file("root/file1", "");
169     atf::utils::create_file("root/file2", "");
170 
171     lutok::do_string(state,
172                      "names = {}\n"
173                      "for file in fs.files('root') do\n"
174                      "    table.insert(names, file)\n"
175                      "end\n"
176                      "table.sort(names)\n"
177                      "return table.concat(names, ' ')", 1);
178     ATF_REQUIRE_EQ(". .. file1 file2", state.to_string());
179     state.pop(1);
180 }
181 
182 
183 ATF_TEST_CASE_WITHOUT_HEAD(files__fail_arg);
184 ATF_TEST_CASE_BODY(files__fail_arg)
185 {
186     lutok::state state;
187     fs::open_fs(state);
188 
189     ATF_REQUIRE_THROW_RE(lutok::error, "Need a string parameter",
190                          lutok::do_string(state, "fs.files({})"));
191     ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
192                          lutok::do_string(state, "fs.files('')"));
193 }
194 
195 
196 ATF_TEST_CASE_WITHOUT_HEAD(files__fail_opendir);
197 ATF_TEST_CASE_BODY(files__fail_opendir)
198 {
199     lutok::state state;
200     fs::open_fs(state);
201 
202     ATF_REQUIRE_THROW_RE(lutok::error, "Failed to open directory",
203                          lutok::do_string(state, "fs.files('root')"));
204 }
205 
206 
207 ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__ok);
208 ATF_TEST_CASE_BODY(is_absolute__ok)
209 {
210     lutok::state state;
211     fs::open_fs(state);
212 
213     lutok::do_string(state, "return fs.is_absolute('my/test//file_foobar')", 1);
214     ATF_REQUIRE(!state.to_boolean());
215     lutok::do_string(state, "return fs.is_absolute('/my/test//file_foobar')", 1);
216     ATF_REQUIRE(state.to_boolean());
217     state.pop(2);
218 }
219 
220 
221 ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__fail);
222 ATF_TEST_CASE_BODY(is_absolute__fail)
223 {
224     lutok::state state;
225     fs::open_fs(state);
226 
227     ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
228                          lutok::do_string(state, "return fs.is_absolute({})", 1));
229     ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
230                          lutok::do_string(state, "return fs.is_absolute('')", 1));
231 }
232 
233 
234 ATF_TEST_CASE_WITHOUT_HEAD(join__ok);
235 ATF_TEST_CASE_BODY(join__ok)
236 {
237     lutok::state state;
238     fs::open_fs(state);
239 
240     lutok::do_string(state, "return fs.join('/a/b///', 'c/d')", 1);
241     ATF_REQUIRE_EQ("/a/b/c/d", state.to_string());
242     state.pop(1);
243 }
244 
245 
246 ATF_TEST_CASE_WITHOUT_HEAD(join__fail);
247 ATF_TEST_CASE_BODY(join__fail)
248 {
249     lutok::state state;
250     fs::open_fs(state);
251 
252     ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
253                          lutok::do_string(state, "return fs.join({}, 'a')", 1));
254     ATF_REQUIRE_THROW_RE(lutok::error, "Need a string",
255                          lutok::do_string(state, "return fs.join('a', {})", 1));
256 
257     ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
258                          lutok::do_string(state, "return fs.join('', 'a')", 1));
259     ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path",
260                          lutok::do_string(state, "return fs.join('a', '')", 1));
261 
262     ATF_REQUIRE_THROW_RE(lutok::error, "Cannot join.*'a/b'.*'/c'",
263                          lutok::do_string(state, "fs.join('a/b', '/c')"));
264 }
265 
266 
267 ATF_INIT_TEST_CASES(tcs)
268 {
269     ATF_ADD_TEST_CASE(tcs, open_fs);
270 
271     ATF_ADD_TEST_CASE(tcs, basename__ok);
272     ATF_ADD_TEST_CASE(tcs, basename__fail);
273 
274     ATF_ADD_TEST_CASE(tcs, dirname__ok);
275     ATF_ADD_TEST_CASE(tcs, dirname__fail);
276 
277     ATF_ADD_TEST_CASE(tcs, exists__ok);
278     ATF_ADD_TEST_CASE(tcs, exists__fail);
279 
280     ATF_ADD_TEST_CASE(tcs, files__none);
281     ATF_ADD_TEST_CASE(tcs, files__some);
282     ATF_ADD_TEST_CASE(tcs, files__fail_arg);
283     ATF_ADD_TEST_CASE(tcs, files__fail_opendir);
284 
285     ATF_ADD_TEST_CASE(tcs, is_absolute__ok);
286     ATF_ADD_TEST_CASE(tcs, is_absolute__fail);
287 
288     ATF_ADD_TEST_CASE(tcs, join__ok);
289     ATF_ADD_TEST_CASE(tcs, join__fail);
290 }
291