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
39namespace fs = utils::fs;
40
41
42ATF_TEST_CASE_WITHOUT_HEAD(open_fs);
43ATF_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
58ATF_TEST_CASE_WITHOUT_HEAD(basename__ok);
59ATF_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
70ATF_TEST_CASE_WITHOUT_HEAD(basename__fail);
71ATF_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
83ATF_TEST_CASE_WITHOUT_HEAD(dirname__ok);
84ATF_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
95ATF_TEST_CASE_WITHOUT_HEAD(dirname__fail);
96ATF_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
108ATF_TEST_CASE_WITHOUT_HEAD(exists__ok);
109ATF_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
126ATF_TEST_CASE_WITHOUT_HEAD(exists__fail);
127ATF_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
139ATF_TEST_CASE_WITHOUT_HEAD(files__none);
140ATF_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
160ATF_TEST_CASE_WITHOUT_HEAD(files__some);
161ATF_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
183ATF_TEST_CASE_WITHOUT_HEAD(files__fail_arg);
184ATF_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
196ATF_TEST_CASE_WITHOUT_HEAD(files__fail_opendir);
197ATF_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
207ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__ok);
208ATF_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
221ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__fail);
222ATF_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
234ATF_TEST_CASE_WITHOUT_HEAD(join__ok);
235ATF_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
246ATF_TEST_CASE_WITHOUT_HEAD(join__fail);
247ATF_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
267ATF_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