1 // Copyright 2010 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 "engine/kyuafile.hpp"
30 
31 #include <stdexcept>
32 #include <typeinfo>
33 
34 #include <atf-c++.hpp>
35 #include <lutok/operations.hpp>
36 #include <lutok/state.ipp>
37 #include <lutok/test_utils.hpp>
38 
39 #include "engine/exceptions.hpp"
40 #include "engine/test_program.hpp"
41 #include "utils/datetime.hpp"
42 #include "utils/format/macros.hpp"
43 #include "utils/fs/operations.hpp"
44 #include "utils/optional.ipp"
45 
46 namespace datetime = utils::datetime;
47 namespace fs = utils::fs;
48 
49 using utils::none;
50 
51 
52 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__empty);
ATF_TEST_CASE_BODY(kyuafile__load__empty)53 ATF_TEST_CASE_BODY(kyuafile__load__empty)
54 {
55     atf::utils::create_file("config", "syntax(2)\n");
56 
57     const engine::kyuafile suite = engine::kyuafile::load(
58         fs::path("config"), none);
59     ATF_REQUIRE_EQ(fs::path("."), suite.source_root());
60     ATF_REQUIRE_EQ(fs::path("."), suite.build_root());
61     ATF_REQUIRE_EQ(0, suite.test_programs().size());
62 }
63 
64 
65 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__some_programs);
ATF_TEST_CASE_BODY(kyuafile__load__some_programs)66 ATF_TEST_CASE_BODY(kyuafile__load__some_programs)
67 {
68     atf::utils::create_file(
69         "config",
70         "syntax(2)\n"
71         "test_suite('one-suite')\n"
72         "atf_test_program{name='1st'}\n"
73         "atf_test_program{name='2nd', test_suite='first'}\n"
74         "plain_test_program{name='3rd'}\n"
75         "plain_test_program{name='4th', test_suite='second'}\n"
76         "include('dir/config')\n");
77 
78     fs::mkdir(fs::path("dir"), 0755);
79     atf::utils::create_file(
80         "dir/config",
81         "syntax(2)\n"
82         "atf_test_program{name='1st', test_suite='other-suite'}\n"
83         "include('subdir/config')\n");
84 
85     fs::mkdir(fs::path("dir/subdir"), 0755);
86     atf::utils::create_file(
87         "dir/subdir/config",
88         "syntax(2)\n"
89         "atf_test_program{name='5th', test_suite='last-suite'}\n");
90 
91     atf::utils::create_file("1st", "");
92     atf::utils::create_file("2nd", "");
93     atf::utils::create_file("3rd", "");
94     atf::utils::create_file("4th", "");
95     atf::utils::create_file("dir/1st", "");
96     atf::utils::create_file("dir/subdir/5th", "");
97 
98     const engine::kyuafile suite = engine::kyuafile::load(
99         fs::path("config"), none);
100     ATF_REQUIRE_EQ(fs::path("."), suite.source_root());
101     ATF_REQUIRE_EQ(fs::path("."), suite.build_root());
102     ATF_REQUIRE_EQ(6, suite.test_programs().size());
103 
104     ATF_REQUIRE_EQ("atf", suite.test_programs()[0]->interface_name());
105     ATF_REQUIRE_EQ(fs::path("1st"), suite.test_programs()[0]->relative_path());
106     ATF_REQUIRE_EQ("one-suite", suite.test_programs()[0]->test_suite_name());
107 
108     ATF_REQUIRE_EQ("atf", suite.test_programs()[1]->interface_name());
109     ATF_REQUIRE_EQ(fs::path("2nd"), suite.test_programs()[1]->relative_path());
110     ATF_REQUIRE_EQ("first", suite.test_programs()[1]->test_suite_name());
111 
112     ATF_REQUIRE_EQ("plain", suite.test_programs()[2]->interface_name());
113     ATF_REQUIRE_EQ(fs::path("3rd"), suite.test_programs()[2]->relative_path());
114     ATF_REQUIRE_EQ("one-suite", suite.test_programs()[2]->test_suite_name());
115 
116     ATF_REQUIRE_EQ("plain", suite.test_programs()[3]->interface_name());
117     ATF_REQUIRE_EQ(fs::path("4th"), suite.test_programs()[3]->relative_path());
118     ATF_REQUIRE_EQ("second", suite.test_programs()[3]->test_suite_name());
119 
120     ATF_REQUIRE_EQ("atf", suite.test_programs()[4]->interface_name());
121     ATF_REQUIRE_EQ(fs::path("dir/1st"),
122                    suite.test_programs()[4]->relative_path());
123     ATF_REQUIRE_EQ("other-suite", suite.test_programs()[4]->test_suite_name());
124 
125     ATF_REQUIRE_EQ("atf", suite.test_programs()[5]->interface_name());
126     ATF_REQUIRE_EQ(fs::path("dir/subdir/5th"),
127                    suite.test_programs()[5]->relative_path());
128     ATF_REQUIRE_EQ("last-suite", suite.test_programs()[5]->test_suite_name());
129 }
130 
131 
132 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__metadata);
ATF_TEST_CASE_BODY(kyuafile__load__metadata)133 ATF_TEST_CASE_BODY(kyuafile__load__metadata)
134 {
135     atf::utils::create_file(
136         "config",
137         "syntax(2)\n"
138         "atf_test_program{name='1st', test_suite='first',"
139         " allowed_architectures='amd64 i386', timeout=15}\n"
140         "plain_test_program{name='2nd', test_suite='second',"
141         " required_files='foo /bar//baz', required_user='root'}\n");
142     atf::utils::create_file("1st", "");
143     atf::utils::create_file("2nd", "");
144 
145     const engine::kyuafile suite = engine::kyuafile::load(
146         fs::path("config"), none);
147     ATF_REQUIRE_EQ(2, suite.test_programs().size());
148 
149     ATF_REQUIRE_EQ("atf", suite.test_programs()[0]->interface_name());
150     ATF_REQUIRE_EQ(fs::path("1st"), suite.test_programs()[0]->relative_path());
151     ATF_REQUIRE_EQ("first", suite.test_programs()[0]->test_suite_name());
152     const engine::metadata md1 = engine::metadata_builder()
153         .add_allowed_architecture("amd64")
154         .add_allowed_architecture("i386")
155         .set_timeout(datetime::delta(15, 0))
156         .build();
157     ATF_REQUIRE_EQ(md1, suite.test_programs()[0]->get_metadata());
158 
159     ATF_REQUIRE_EQ("plain", suite.test_programs()[1]->interface_name());
160     ATF_REQUIRE_EQ(fs::path("2nd"), suite.test_programs()[1]->relative_path());
161     ATF_REQUIRE_EQ("second", suite.test_programs()[1]->test_suite_name());
162     const engine::metadata md2 = engine::metadata_builder()
163         .add_required_file(fs::path("foo"))
164         .add_required_file(fs::path("/bar/baz"))
165         .set_required_user("root")
166         .build();
167     ATF_REQUIRE_EQ(md2, suite.test_programs()[1]->get_metadata());
168 }
169 
170 
171 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__current_directory);
ATF_TEST_CASE_BODY(kyuafile__load__current_directory)172 ATF_TEST_CASE_BODY(kyuafile__load__current_directory)
173 {
174     atf::utils::create_file(
175         "config",
176         "syntax(2)\n"
177         "atf_test_program{name='one', test_suite='first'}\n"
178         "include('config2')\n");
179 
180     atf::utils::create_file(
181         "config2",
182         "syntax(2)\n"
183         "test_suite('second')\n"
184         "atf_test_program{name='two'}\n");
185 
186     atf::utils::create_file("one", "");
187     atf::utils::create_file("two", "");
188 
189     const engine::kyuafile suite = engine::kyuafile::load(
190         fs::path("config"), none);
191     ATF_REQUIRE_EQ(fs::path("."), suite.source_root());
192     ATF_REQUIRE_EQ(fs::path("."), suite.build_root());
193     ATF_REQUIRE_EQ(2, suite.test_programs().size());
194     ATF_REQUIRE_EQ(fs::path("one"), suite.test_programs()[0]->relative_path());
195     ATF_REQUIRE_EQ("first", suite.test_programs()[0]->test_suite_name());
196     ATF_REQUIRE_EQ(fs::path("two"),
197                    suite.test_programs()[1]->relative_path());
198     ATF_REQUIRE_EQ("second", suite.test_programs()[1]->test_suite_name());
199 }
200 
201 
202 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__other_directory);
ATF_TEST_CASE_BODY(kyuafile__load__other_directory)203 ATF_TEST_CASE_BODY(kyuafile__load__other_directory)
204 {
205     fs::mkdir(fs::path("root"), 0755);
206     atf::utils::create_file(
207         "root/config",
208         "syntax(2)\n"
209         "test_suite('abc')\n"
210         "atf_test_program{name='one'}\n"
211         "include('dir/config')\n");
212 
213     fs::mkdir(fs::path("root/dir"), 0755);
214     atf::utils::create_file(
215         "root/dir/config",
216         "syntax(2)\n"
217         "test_suite('foo')\n"
218         "atf_test_program{name='two', test_suite='def'}\n"
219         "atf_test_program{name='three'}\n");
220 
221     atf::utils::create_file("root/one", "");
222     atf::utils::create_file("root/dir/two", "");
223     atf::utils::create_file("root/dir/three", "");
224 
225     const engine::kyuafile suite = engine::kyuafile::load(
226         fs::path("root/config"), none);
227     ATF_REQUIRE_EQ(fs::path("root"), suite.source_root());
228     ATF_REQUIRE_EQ(fs::path("root"), suite.build_root());
229     ATF_REQUIRE_EQ(3, suite.test_programs().size());
230     ATF_REQUIRE_EQ(fs::path("one"), suite.test_programs()[0]->relative_path());
231     ATF_REQUIRE_EQ("abc", suite.test_programs()[0]->test_suite_name());
232     ATF_REQUIRE_EQ(fs::path("dir/two"),
233                    suite.test_programs()[1]->relative_path());
234     ATF_REQUIRE_EQ("def", suite.test_programs()[1]->test_suite_name());
235     ATF_REQUIRE_EQ(fs::path("dir/three"),
236                    suite.test_programs()[2]->relative_path());
237     ATF_REQUIRE_EQ("foo", suite.test_programs()[2]->test_suite_name());
238 }
239 
240 
241 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__build_directory);
ATF_TEST_CASE_BODY(kyuafile__load__build_directory)242 ATF_TEST_CASE_BODY(kyuafile__load__build_directory)
243 {
244     fs::mkdir(fs::path("srcdir"), 0755);
245     atf::utils::create_file(
246         "srcdir/config",
247         "syntax(2)\n"
248         "test_suite('abc')\n"
249         "atf_test_program{name='one'}\n"
250         "include('dir/config')\n");
251 
252     fs::mkdir(fs::path("srcdir/dir"), 0755);
253     atf::utils::create_file(
254         "srcdir/dir/config",
255         "syntax(2)\n"
256         "test_suite('foo')\n"
257         "atf_test_program{name='two', test_suite='def'}\n"
258         "atf_test_program{name='three'}\n");
259 
260     fs::mkdir(fs::path("builddir"), 0755);
261     atf::utils::create_file("builddir/one", "");
262     fs::mkdir(fs::path("builddir/dir"), 0755);
263     atf::utils::create_file("builddir/dir/two", "");
264     atf::utils::create_file("builddir/dir/three", "");
265 
266     const engine::kyuafile suite = engine::kyuafile::load(
267         fs::path("srcdir/config"), utils::make_optional(fs::path("builddir")));
268     ATF_REQUIRE_EQ(fs::path("srcdir"), suite.source_root());
269     ATF_REQUIRE_EQ(fs::path("builddir"), suite.build_root());
270     ATF_REQUIRE_EQ(3, suite.test_programs().size());
271     ATF_REQUIRE_EQ(fs::path("builddir/one").to_absolute(),
272                    suite.test_programs()[0]->absolute_path());
273     ATF_REQUIRE_EQ(fs::path("one"), suite.test_programs()[0]->relative_path());
274     ATF_REQUIRE_EQ("abc", suite.test_programs()[0]->test_suite_name());
275     ATF_REQUIRE_EQ(fs::path("builddir/dir/two").to_absolute(),
276                    suite.test_programs()[1]->absolute_path());
277     ATF_REQUIRE_EQ(fs::path("dir/two"),
278                    suite.test_programs()[1]->relative_path());
279     ATF_REQUIRE_EQ("def", suite.test_programs()[1]->test_suite_name());
280     ATF_REQUIRE_EQ(fs::path("builddir/dir/three").to_absolute(),
281                    suite.test_programs()[2]->absolute_path());
282     ATF_REQUIRE_EQ(fs::path("dir/three"),
283                    suite.test_programs()[2]->relative_path());
284     ATF_REQUIRE_EQ("foo", suite.test_programs()[2]->test_suite_name());
285 }
286 
287 
288 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__test_program_not_basename);
ATF_TEST_CASE_BODY(kyuafile__load__test_program_not_basename)289 ATF_TEST_CASE_BODY(kyuafile__load__test_program_not_basename)
290 {
291     atf::utils::create_file(
292         "config",
293         "syntax(2)\n"
294         "test_suite('abc')\n"
295         "atf_test_program{name='one'}\n"
296         "atf_test_program{name='./ls'}\n");
297 
298     atf::utils::create_file("one", "");
299     ATF_REQUIRE_THROW_RE(engine::load_error, "./ls.*path components",
300                          engine::kyuafile::load(fs::path("config"), none));
301 }
302 
303 
304 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__lua_error);
ATF_TEST_CASE_BODY(kyuafile__load__lua_error)305 ATF_TEST_CASE_BODY(kyuafile__load__lua_error)
306 {
307     atf::utils::create_file("config", "this syntax is invalid\n");
308 
309     ATF_REQUIRE_THROW(engine::load_error, engine::kyuafile::load(
310                           fs::path("config"), none));
311 }
312 
313 
314 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__not_called);
ATF_TEST_CASE_BODY(kyuafile__load__syntax__not_called)315 ATF_TEST_CASE_BODY(kyuafile__load__syntax__not_called)
316 {
317     atf::utils::create_file("config", "");
318 
319     ATF_REQUIRE_THROW_RE(engine::load_error, "syntax.* never called",
320                          engine::kyuafile::load(fs::path("config"), none));
321 }
322 
323 
324 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__deprecated_format);
ATF_TEST_CASE_BODY(kyuafile__load__syntax__deprecated_format)325 ATF_TEST_CASE_BODY(kyuafile__load__syntax__deprecated_format)
326 {
327     atf::utils::create_file("config", "syntax('kyuafile', 1)\n");
328     (void)engine::kyuafile::load(fs::path("config"), none);
329 
330     atf::utils::create_file("config", "syntax('foo', 1)\n");
331     ATF_REQUIRE_THROW_RE(engine::load_error, "must be 'kyuafile'",
332                          engine::kyuafile::load(fs::path("config"), none));
333 
334     atf::utils::create_file("config", "syntax('config', 2)\n");
335     ATF_REQUIRE_THROW_RE(engine::load_error, "only takes one argument",
336                          engine::kyuafile::load(fs::path("config"), none));
337 }
338 
339 
340 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__twice);
ATF_TEST_CASE_BODY(kyuafile__load__syntax__twice)341 ATF_TEST_CASE_BODY(kyuafile__load__syntax__twice)
342 {
343     atf::utils::create_file(
344         "config",
345         "syntax(2)\n"
346         "syntax(2)\n");
347 
348     ATF_REQUIRE_THROW_RE(engine::load_error, "Can only call syntax.* once",
349                          engine::kyuafile::load(fs::path("config"), none));
350 }
351 
352 
353 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__bad_version);
ATF_TEST_CASE_BODY(kyuafile__load__syntax__bad_version)354 ATF_TEST_CASE_BODY(kyuafile__load__syntax__bad_version)
355 {
356     atf::utils::create_file("config", "syntax(12)\n");
357 
358     ATF_REQUIRE_THROW_RE(engine::load_error, "Unsupported file version 12",
359                          engine::kyuafile::load(fs::path("config"), none));
360 }
361 
362 
363 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__test_suite__twice);
ATF_TEST_CASE_BODY(kyuafile__load__test_suite__twice)364 ATF_TEST_CASE_BODY(kyuafile__load__test_suite__twice)
365 {
366     atf::utils::create_file(
367         "config",
368         "syntax(2)\n"
369         "test_suite('foo')\n"
370         "test_suite('bar')\n");
371 
372     ATF_REQUIRE_THROW_RE(engine::load_error, "Can only call test_suite.* once",
373                          engine::kyuafile::load(fs::path("config"), none));
374 }
375 
376 
377 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__missing_file);
ATF_TEST_CASE_BODY(kyuafile__load__missing_file)378 ATF_TEST_CASE_BODY(kyuafile__load__missing_file)
379 {
380     ATF_REQUIRE_THROW_RE(engine::load_error, "Load of 'missing' failed",
381                          engine::kyuafile::load(fs::path("missing"), none));
382 }
383 
384 
385 ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__missing_test_program);
ATF_TEST_CASE_BODY(kyuafile__load__missing_test_program)386 ATF_TEST_CASE_BODY(kyuafile__load__missing_test_program)
387 {
388     atf::utils::create_file(
389         "config",
390         "syntax(2)\n"
391         "atf_test_program{name='one', test_suite='first'}\n"
392         "atf_test_program{name='two', test_suite='first'}\n");
393 
394     atf::utils::create_file("one", "");
395 
396     ATF_REQUIRE_THROW_RE(engine::load_error, "Non-existent.*'two'",
397                          engine::kyuafile::load(fs::path("config"), none));
398 }
399 
400 
ATF_INIT_TEST_CASES(tcs)401 ATF_INIT_TEST_CASES(tcs)
402 {
403     ATF_ADD_TEST_CASE(tcs, kyuafile__load__empty);
404     ATF_ADD_TEST_CASE(tcs, kyuafile__load__some_programs);
405     ATF_ADD_TEST_CASE(tcs, kyuafile__load__metadata);
406     ATF_ADD_TEST_CASE(tcs, kyuafile__load__current_directory);
407     ATF_ADD_TEST_CASE(tcs, kyuafile__load__other_directory);
408     ATF_ADD_TEST_CASE(tcs, kyuafile__load__build_directory);
409     ATF_ADD_TEST_CASE(tcs, kyuafile__load__test_program_not_basename);
410     ATF_ADD_TEST_CASE(tcs, kyuafile__load__lua_error);
411     ATF_ADD_TEST_CASE(tcs, kyuafile__load__syntax__not_called);
412     ATF_ADD_TEST_CASE(tcs, kyuafile__load__syntax__deprecated_format);
413     ATF_ADD_TEST_CASE(tcs, kyuafile__load__syntax__twice);
414     ATF_ADD_TEST_CASE(tcs, kyuafile__load__syntax__bad_version);
415     ATF_ADD_TEST_CASE(tcs, kyuafile__load__test_suite__twice);
416     ATF_ADD_TEST_CASE(tcs, kyuafile__load__missing_file);
417     ATF_ADD_TEST_CASE(tcs, kyuafile__load__missing_test_program);
418 }
419