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
46namespace datetime = utils::datetime;
47namespace fs = utils::fs;
48
49using utils::none;
50
51
52ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__empty);
53ATF_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
65ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__some_programs);
66ATF_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
132ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__metadata);
133ATF_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
171ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__current_directory);
172ATF_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
202ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__other_directory);
203ATF_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
241ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__build_directory);
242ATF_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
288ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__test_program_not_basename);
289ATF_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
304ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__lua_error);
305ATF_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
314ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__not_called);
315ATF_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
324ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__deprecated_format);
325ATF_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
340ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__twice);
341ATF_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
353ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__bad_version);
354ATF_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
363ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__test_suite__twice);
364ATF_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
377ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__missing_file);
378ATF_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
385ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__missing_test_program);
386ATF_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
401ATF_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