xref: /freebsd-src/contrib/kyua/store/schema_inttest.cpp (revision b0d29bc47dba79f6f38e67eabadfb4b32ffd9390)
1*b0d29bc4SBrooks Davis // Copyright 2013 The Kyua Authors.
2*b0d29bc4SBrooks Davis // All rights reserved.
3*b0d29bc4SBrooks Davis //
4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without
5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are
6*b0d29bc4SBrooks Davis // met:
7*b0d29bc4SBrooks Davis //
8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright
9*b0d29bc4SBrooks Davis //   notice, this list of conditions and the following disclaimer.
10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
11*b0d29bc4SBrooks Davis //   notice, this list of conditions and the following disclaimer in the
12*b0d29bc4SBrooks Davis //   documentation and/or other materials provided with the distribution.
13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
14*b0d29bc4SBrooks Davis //   may be used to endorse or promote products derived from this software
15*b0d29bc4SBrooks Davis //   without specific prior written permission.
16*b0d29bc4SBrooks Davis //
17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*b0d29bc4SBrooks Davis 
29*b0d29bc4SBrooks Davis #include <map>
30*b0d29bc4SBrooks Davis 
31*b0d29bc4SBrooks Davis #include <atf-c++.hpp>
32*b0d29bc4SBrooks Davis 
33*b0d29bc4SBrooks Davis #include "model/context.hpp"
34*b0d29bc4SBrooks Davis #include "model/metadata.hpp"
35*b0d29bc4SBrooks Davis #include "model/test_program.hpp"
36*b0d29bc4SBrooks Davis #include "model/test_result.hpp"
37*b0d29bc4SBrooks Davis #include "store/migrate.hpp"
38*b0d29bc4SBrooks Davis #include "store/read_backend.hpp"
39*b0d29bc4SBrooks Davis #include "store/read_transaction.hpp"
40*b0d29bc4SBrooks Davis #include "store/write_backend.hpp"
41*b0d29bc4SBrooks Davis #include "utils/datetime.hpp"
42*b0d29bc4SBrooks Davis #include "utils/env.hpp"
43*b0d29bc4SBrooks Davis #include "utils/format/macros.hpp"
44*b0d29bc4SBrooks Davis #include "utils/fs/path.hpp"
45*b0d29bc4SBrooks Davis #include "utils/logging/operations.hpp"
46*b0d29bc4SBrooks Davis #include "utils/sqlite/database.hpp"
47*b0d29bc4SBrooks Davis #include "utils/stream.hpp"
48*b0d29bc4SBrooks Davis #include "utils/units.hpp"
49*b0d29bc4SBrooks Davis 
50*b0d29bc4SBrooks Davis namespace datetime = utils::datetime;
51*b0d29bc4SBrooks Davis namespace fs = utils::fs;
52*b0d29bc4SBrooks Davis namespace logging = utils::logging;
53*b0d29bc4SBrooks Davis namespace sqlite = utils::sqlite;
54*b0d29bc4SBrooks Davis namespace units = utils::units;
55*b0d29bc4SBrooks Davis 
56*b0d29bc4SBrooks Davis 
57*b0d29bc4SBrooks Davis namespace {
58*b0d29bc4SBrooks Davis 
59*b0d29bc4SBrooks Davis 
60*b0d29bc4SBrooks Davis /// Gets a data file from the tests directory.
61*b0d29bc4SBrooks Davis ///
62*b0d29bc4SBrooks Davis /// We cannot use the srcdir property because the required files are not there
63*b0d29bc4SBrooks Davis /// when building with an object directory.  In those cases, the data files
64*b0d29bc4SBrooks Davis /// remainin the source directory while the resulting test program is in the
65*b0d29bc4SBrooks Davis /// object directory, thus having the wrong value for its srcdir property.
66*b0d29bc4SBrooks Davis ///
67*b0d29bc4SBrooks Davis /// \param name Basename of the test data file to query.
68*b0d29bc4SBrooks Davis ///
69*b0d29bc4SBrooks Davis /// \return The actual path to the requested data file.
70*b0d29bc4SBrooks Davis static fs::path
testdata_file(const std::string & name)71*b0d29bc4SBrooks Davis testdata_file(const std::string& name)
72*b0d29bc4SBrooks Davis {
73*b0d29bc4SBrooks Davis     const fs::path testdatadir(utils::getenv_with_default(
74*b0d29bc4SBrooks Davis         "KYUA_STORETESTDATADIR", KYUA_STORETESTDATADIR));
75*b0d29bc4SBrooks Davis     return testdatadir / name;
76*b0d29bc4SBrooks Davis }
77*b0d29bc4SBrooks Davis 
78*b0d29bc4SBrooks Davis 
79*b0d29bc4SBrooks Davis /// Validates the contents of the action with identifier 1.
80*b0d29bc4SBrooks Davis ///
81*b0d29bc4SBrooks Davis /// \param dbpath Path to the database in which to check the action contents.
82*b0d29bc4SBrooks Davis static void
check_action_1(const fs::path & dbpath)83*b0d29bc4SBrooks Davis check_action_1(const fs::path& dbpath)
84*b0d29bc4SBrooks Davis {
85*b0d29bc4SBrooks Davis     store::read_backend backend = store::read_backend::open_ro(dbpath);
86*b0d29bc4SBrooks Davis     store::read_transaction transaction = backend.start_read();
87*b0d29bc4SBrooks Davis 
88*b0d29bc4SBrooks Davis     const fs::path root("/some/root");
89*b0d29bc4SBrooks Davis     std::map< std::string, std::string > environment;
90*b0d29bc4SBrooks Davis     const model::context context(root, environment);
91*b0d29bc4SBrooks Davis 
92*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(context, transaction.get_context());
93*b0d29bc4SBrooks Davis 
94*b0d29bc4SBrooks Davis     store::results_iterator iter = transaction.get_results();
95*b0d29bc4SBrooks Davis     ATF_REQUIRE(!iter);
96*b0d29bc4SBrooks Davis }
97*b0d29bc4SBrooks Davis 
98*b0d29bc4SBrooks Davis 
99*b0d29bc4SBrooks Davis /// Validates the contents of the action with identifier 2.
100*b0d29bc4SBrooks Davis ///
101*b0d29bc4SBrooks Davis /// \param dbpath Path to the database in which to check the action contents.
102*b0d29bc4SBrooks Davis static void
check_action_2(const fs::path & dbpath)103*b0d29bc4SBrooks Davis check_action_2(const fs::path& dbpath)
104*b0d29bc4SBrooks Davis {
105*b0d29bc4SBrooks Davis     store::read_backend backend = store::read_backend::open_ro(dbpath);
106*b0d29bc4SBrooks Davis     store::read_transaction transaction = backend.start_read();
107*b0d29bc4SBrooks Davis 
108*b0d29bc4SBrooks Davis     const fs::path root("/test/suite/root");
109*b0d29bc4SBrooks Davis     std::map< std::string, std::string > environment;
110*b0d29bc4SBrooks Davis     environment["HOME"] = "/home/test";
111*b0d29bc4SBrooks Davis     environment["PATH"] = "/bin:/usr/bin";
112*b0d29bc4SBrooks Davis     const model::context context(root, environment);
113*b0d29bc4SBrooks Davis 
114*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(context, transaction.get_context());
115*b0d29bc4SBrooks Davis 
116*b0d29bc4SBrooks Davis     const model::test_program test_program_1 = model::test_program_builder(
117*b0d29bc4SBrooks Davis         "plain", fs::path("foo_test"), fs::path("/test/suite/root"),
118*b0d29bc4SBrooks Davis         "suite-name")
119*b0d29bc4SBrooks Davis         .add_test_case("main")
120*b0d29bc4SBrooks Davis         .build();
121*b0d29bc4SBrooks Davis     const model::test_result result_1(model::test_result_passed);
122*b0d29bc4SBrooks Davis 
123*b0d29bc4SBrooks Davis     const model::test_program test_program_2 = model::test_program_builder(
124*b0d29bc4SBrooks Davis         "plain", fs::path("subdir/another_test"), fs::path("/test/suite/root"),
125*b0d29bc4SBrooks Davis         "subsuite-name")
126*b0d29bc4SBrooks Davis         .add_test_case("main",
127*b0d29bc4SBrooks Davis                        model::metadata_builder()
128*b0d29bc4SBrooks Davis                        .set_timeout(datetime::delta(10, 0))
129*b0d29bc4SBrooks Davis                        .build())
130*b0d29bc4SBrooks Davis         .set_metadata(model::metadata_builder()
131*b0d29bc4SBrooks Davis                       .set_timeout(datetime::delta(10, 0))
132*b0d29bc4SBrooks Davis                       .build())
133*b0d29bc4SBrooks Davis         .build();
134*b0d29bc4SBrooks Davis     const model::test_result result_2(model::test_result_failed,
135*b0d29bc4SBrooks Davis                                       "Exited with code 1");
136*b0d29bc4SBrooks Davis 
137*b0d29bc4SBrooks Davis     const model::test_program test_program_3 = model::test_program_builder(
138*b0d29bc4SBrooks Davis         "plain", fs::path("subdir/bar_test"), fs::path("/test/suite/root"),
139*b0d29bc4SBrooks Davis         "subsuite-name")
140*b0d29bc4SBrooks Davis         .add_test_case("main")
141*b0d29bc4SBrooks Davis         .build();
142*b0d29bc4SBrooks Davis     const model::test_result result_3(model::test_result_broken,
143*b0d29bc4SBrooks Davis                                       "Received signal 1");
144*b0d29bc4SBrooks Davis 
145*b0d29bc4SBrooks Davis     const model::test_program test_program_4 = model::test_program_builder(
146*b0d29bc4SBrooks Davis         "plain", fs::path("top_test"), fs::path("/test/suite/root"),
147*b0d29bc4SBrooks Davis         "suite-name")
148*b0d29bc4SBrooks Davis         .add_test_case("main")
149*b0d29bc4SBrooks Davis         .build();
150*b0d29bc4SBrooks Davis     const model::test_result result_4(model::test_result_expected_failure,
151*b0d29bc4SBrooks Davis                                       "Known bug");
152*b0d29bc4SBrooks Davis 
153*b0d29bc4SBrooks Davis     const model::test_program test_program_5 = model::test_program_builder(
154*b0d29bc4SBrooks Davis         "plain", fs::path("last_test"), fs::path("/test/suite/root"),
155*b0d29bc4SBrooks Davis         "suite-name")
156*b0d29bc4SBrooks Davis         .add_test_case("main")
157*b0d29bc4SBrooks Davis         .build();
158*b0d29bc4SBrooks Davis     const model::test_result result_5(model::test_result_skipped,
159*b0d29bc4SBrooks Davis                                       "Does not apply");
160*b0d29bc4SBrooks Davis 
161*b0d29bc4SBrooks Davis     store::results_iterator iter = transaction.get_results();
162*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
163*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_1, *iter.test_program());
164*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("main", iter.test_case_name());
165*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_1, iter.result());
166*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
167*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
168*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643611000000LL, iter.start_time().to_microseconds());
169*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643621000500LL, iter.end_time().to_microseconds());
170*b0d29bc4SBrooks Davis 
171*b0d29bc4SBrooks Davis     ++iter;
172*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
173*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_5, *iter.test_program());
174*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("main", iter.test_case_name());
175*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_5, iter.result());
176*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
177*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
178*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643632000000LL, iter.start_time().to_microseconds());
179*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643638000000LL, iter.end_time().to_microseconds());
180*b0d29bc4SBrooks Davis 
181*b0d29bc4SBrooks Davis     ++iter;
182*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
183*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_2, *iter.test_program());
184*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("main", iter.test_case_name());
185*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_2, iter.result());
186*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("Test stdout", iter.stdout_contents());
187*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("Test stderr", iter.stderr_contents());
188*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643622001200LL, iter.start_time().to_microseconds());
189*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643622900021LL, iter.end_time().to_microseconds());
190*b0d29bc4SBrooks Davis 
191*b0d29bc4SBrooks Davis     ++iter;
192*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
193*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_3, *iter.test_program());
194*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("main", iter.test_case_name());
195*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_3, iter.result());
196*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
197*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
198*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643623500000LL, iter.start_time().to_microseconds());
199*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643630981932LL, iter.end_time().to_microseconds());
200*b0d29bc4SBrooks Davis 
201*b0d29bc4SBrooks Davis     ++iter;
202*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
203*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_4, *iter.test_program());
204*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("main", iter.test_case_name());
205*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_4, iter.result());
206*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
207*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
208*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643631000000LL, iter.start_time().to_microseconds());
209*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357643631020000LL, iter.end_time().to_microseconds());
210*b0d29bc4SBrooks Davis 
211*b0d29bc4SBrooks Davis     ++iter;
212*b0d29bc4SBrooks Davis     ATF_REQUIRE(!iter);
213*b0d29bc4SBrooks Davis }
214*b0d29bc4SBrooks Davis 
215*b0d29bc4SBrooks Davis 
216*b0d29bc4SBrooks Davis /// Validates the contents of the action with identifier 3.
217*b0d29bc4SBrooks Davis ///
218*b0d29bc4SBrooks Davis /// \param dbpath Path to the database in which to check the action contents.
219*b0d29bc4SBrooks Davis static void
check_action_3(const fs::path & dbpath)220*b0d29bc4SBrooks Davis check_action_3(const fs::path& dbpath)
221*b0d29bc4SBrooks Davis {
222*b0d29bc4SBrooks Davis     store::read_backend backend = store::read_backend::open_ro(dbpath);
223*b0d29bc4SBrooks Davis     store::read_transaction transaction = backend.start_read();
224*b0d29bc4SBrooks Davis 
225*b0d29bc4SBrooks Davis     const fs::path root("/usr/tests");
226*b0d29bc4SBrooks Davis     std::map< std::string, std::string > environment;
227*b0d29bc4SBrooks Davis     environment["PATH"] = "/bin:/usr/bin";
228*b0d29bc4SBrooks Davis     const model::context context(root, environment);
229*b0d29bc4SBrooks Davis 
230*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(context, transaction.get_context());
231*b0d29bc4SBrooks Davis 
232*b0d29bc4SBrooks Davis     const model::test_program test_program_6 = model::test_program_builder(
233*b0d29bc4SBrooks Davis         "atf", fs::path("complex_test"), fs::path("/usr/tests"),
234*b0d29bc4SBrooks Davis         "suite-name")
235*b0d29bc4SBrooks Davis         .add_test_case("this_passes")
236*b0d29bc4SBrooks Davis         .add_test_case("this_fails",
237*b0d29bc4SBrooks Davis                        model::metadata_builder()
238*b0d29bc4SBrooks Davis                        .set_description("Test description")
239*b0d29bc4SBrooks Davis                        .set_has_cleanup(true)
240*b0d29bc4SBrooks Davis                        .set_required_memory(units::bytes(128))
241*b0d29bc4SBrooks Davis                        .set_required_user("root")
242*b0d29bc4SBrooks Davis                        .build())
243*b0d29bc4SBrooks Davis         .add_test_case("this_skips",
244*b0d29bc4SBrooks Davis                        model::metadata_builder()
245*b0d29bc4SBrooks Davis                        .add_allowed_architecture("powerpc")
246*b0d29bc4SBrooks Davis                        .add_allowed_architecture("x86_64")
247*b0d29bc4SBrooks Davis                        .add_allowed_platform("amd64")
248*b0d29bc4SBrooks Davis                        .add_allowed_platform("macppc")
249*b0d29bc4SBrooks Davis                        .add_required_config("X-foo")
250*b0d29bc4SBrooks Davis                        .add_required_config("unprivileged_user")
251*b0d29bc4SBrooks Davis                        .add_required_file(fs::path("/the/data/file"))
252*b0d29bc4SBrooks Davis                        .add_required_program(fs::path("/bin/ls"))
253*b0d29bc4SBrooks Davis                        .add_required_program(fs::path("cp"))
254*b0d29bc4SBrooks Davis                        .set_description("Test explanation")
255*b0d29bc4SBrooks Davis                        .set_has_cleanup(true)
256*b0d29bc4SBrooks Davis                        .set_required_memory(units::bytes(512))
257*b0d29bc4SBrooks Davis                        .set_required_user("unprivileged")
258*b0d29bc4SBrooks Davis                        .set_timeout(datetime::delta(600, 0))
259*b0d29bc4SBrooks Davis                        .build())
260*b0d29bc4SBrooks Davis         .build();
261*b0d29bc4SBrooks Davis     const model::test_result result_6(model::test_result_passed);
262*b0d29bc4SBrooks Davis     const model::test_result result_7(model::test_result_failed,
263*b0d29bc4SBrooks Davis                                       "Some reason");
264*b0d29bc4SBrooks Davis     const model::test_result result_8(model::test_result_skipped,
265*b0d29bc4SBrooks Davis                                       "Another reason");
266*b0d29bc4SBrooks Davis 
267*b0d29bc4SBrooks Davis     const model::test_program test_program_7 = model::test_program_builder(
268*b0d29bc4SBrooks Davis         "atf", fs::path("simple_test"), fs::path("/usr/tests"),
269*b0d29bc4SBrooks Davis         "subsuite-name")
270*b0d29bc4SBrooks Davis         .add_test_case("main",
271*b0d29bc4SBrooks Davis                        model::metadata_builder()
272*b0d29bc4SBrooks Davis                        .set_description("More text")
273*b0d29bc4SBrooks Davis                        .set_has_cleanup(true)
274*b0d29bc4SBrooks Davis                        .set_required_memory(units::bytes(128))
275*b0d29bc4SBrooks Davis                        .set_required_user("unprivileged")
276*b0d29bc4SBrooks Davis                        .build())
277*b0d29bc4SBrooks Davis         .build();
278*b0d29bc4SBrooks Davis     const model::test_result result_9(model::test_result_failed,
279*b0d29bc4SBrooks Davis                                       "Exited with code 1");
280*b0d29bc4SBrooks Davis 
281*b0d29bc4SBrooks Davis     store::results_iterator iter = transaction.get_results();
282*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
283*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_6, *iter.test_program());
284*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("this_fails", iter.test_case_name());
285*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_7, iter.result());
286*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
287*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
288*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357648719000000LL, iter.start_time().to_microseconds());
289*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357648720897182LL, iter.end_time().to_microseconds());
290*b0d29bc4SBrooks Davis 
291*b0d29bc4SBrooks Davis     ++iter;
292*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
293*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_6, *iter.test_program());
294*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("this_passes", iter.test_case_name());
295*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_6, iter.result());
296*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
297*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
298*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357648712000000LL, iter.start_time().to_microseconds());
299*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357648718000000LL, iter.end_time().to_microseconds());
300*b0d29bc4SBrooks Davis 
301*b0d29bc4SBrooks Davis     ++iter;
302*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
303*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_6, *iter.test_program());
304*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("this_skips", iter.test_case_name());
305*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_8, iter.result());
306*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("Another stdout", iter.stdout_contents());
307*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
308*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357648729182013LL, iter.start_time().to_microseconds());
309*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357648730000000LL, iter.end_time().to_microseconds());
310*b0d29bc4SBrooks Davis 
311*b0d29bc4SBrooks Davis     ++iter;
312*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
313*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_7, *iter.test_program());
314*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("main", iter.test_case_name());
315*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_9, iter.result());
316*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
317*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("Another stderr", iter.stderr_contents());
318*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357648740120000LL, iter.start_time().to_microseconds());
319*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357648750081700LL, iter.end_time().to_microseconds());
320*b0d29bc4SBrooks Davis 
321*b0d29bc4SBrooks Davis     ++iter;
322*b0d29bc4SBrooks Davis     ATF_REQUIRE(!iter);
323*b0d29bc4SBrooks Davis }
324*b0d29bc4SBrooks Davis 
325*b0d29bc4SBrooks Davis 
326*b0d29bc4SBrooks Davis /// Validates the contents of the action with identifier 4.
327*b0d29bc4SBrooks Davis ///
328*b0d29bc4SBrooks Davis /// \param dbpath Path to the database in which to check the action contents.
329*b0d29bc4SBrooks Davis static void
check_action_4(const fs::path & dbpath)330*b0d29bc4SBrooks Davis check_action_4(const fs::path& dbpath)
331*b0d29bc4SBrooks Davis {
332*b0d29bc4SBrooks Davis     store::read_backend backend = store::read_backend::open_ro(dbpath);
333*b0d29bc4SBrooks Davis     store::read_transaction transaction = backend.start_read();
334*b0d29bc4SBrooks Davis 
335*b0d29bc4SBrooks Davis     const fs::path root("/usr/tests");
336*b0d29bc4SBrooks Davis     std::map< std::string, std::string > environment;
337*b0d29bc4SBrooks Davis     environment["LANG"] = "C";
338*b0d29bc4SBrooks Davis     environment["PATH"] = "/bin:/usr/bin";
339*b0d29bc4SBrooks Davis     environment["TERM"] = "xterm";
340*b0d29bc4SBrooks Davis     const model::context context(root, environment);
341*b0d29bc4SBrooks Davis 
342*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(context, transaction.get_context());
343*b0d29bc4SBrooks Davis 
344*b0d29bc4SBrooks Davis     const model::test_program test_program_8 = model::test_program_builder(
345*b0d29bc4SBrooks Davis         "plain", fs::path("subdir/another_test"), fs::path("/usr/tests"),
346*b0d29bc4SBrooks Davis         "subsuite-name")
347*b0d29bc4SBrooks Davis         .add_test_case("main",
348*b0d29bc4SBrooks Davis                        model::metadata_builder()
349*b0d29bc4SBrooks Davis                        .set_timeout(datetime::delta(10, 0))
350*b0d29bc4SBrooks Davis                        .build())
351*b0d29bc4SBrooks Davis         .set_metadata(model::metadata_builder()
352*b0d29bc4SBrooks Davis                       .set_timeout(datetime::delta(10, 0))
353*b0d29bc4SBrooks Davis                       .build())
354*b0d29bc4SBrooks Davis         .build();
355*b0d29bc4SBrooks Davis     const model::test_result result_10(model::test_result_failed,
356*b0d29bc4SBrooks Davis                                        "Exit failure");
357*b0d29bc4SBrooks Davis 
358*b0d29bc4SBrooks Davis     const model::test_program test_program_9 = model::test_program_builder(
359*b0d29bc4SBrooks Davis         "atf", fs::path("complex_test"), fs::path("/usr/tests"),
360*b0d29bc4SBrooks Davis         "suite-name")
361*b0d29bc4SBrooks Davis         .add_test_case("this_passes")
362*b0d29bc4SBrooks Davis         .add_test_case("this_fails",
363*b0d29bc4SBrooks Davis                        model::metadata_builder()
364*b0d29bc4SBrooks Davis                        .set_description("Test description")
365*b0d29bc4SBrooks Davis                        .set_required_user("root")
366*b0d29bc4SBrooks Davis                        .build())
367*b0d29bc4SBrooks Davis         .build();
368*b0d29bc4SBrooks Davis     const model::test_result result_11(model::test_result_passed);
369*b0d29bc4SBrooks Davis     const model::test_result result_12(model::test_result_failed,
370*b0d29bc4SBrooks Davis                                        "Some reason");
371*b0d29bc4SBrooks Davis 
372*b0d29bc4SBrooks Davis     store::results_iterator iter = transaction.get_results();
373*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
374*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_9, *iter.test_program());
375*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("this_fails", iter.test_case_name());
376*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_12, iter.result());
377*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
378*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
379*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357644397100000LL, iter.start_time().to_microseconds());
380*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357644399005000LL, iter.end_time().to_microseconds());
381*b0d29bc4SBrooks Davis 
382*b0d29bc4SBrooks Davis     ++iter;
383*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
384*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_9, *iter.test_program());
385*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("this_passes", iter.test_case_name());
386*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_11, iter.result());
387*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stdout_contents().empty());
388*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter.stderr_contents().empty());
389*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357644396500000LL, iter.start_time().to_microseconds());
390*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357644397000000LL, iter.end_time().to_microseconds());
391*b0d29bc4SBrooks Davis 
392*b0d29bc4SBrooks Davis     ++iter;
393*b0d29bc4SBrooks Davis     ATF_REQUIRE(iter);
394*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(test_program_8, *iter.test_program());
395*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("main", iter.test_case_name());
396*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(result_10, iter.result());
397*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("Test stdout", iter.stdout_contents());
398*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("Test stderr", iter.stderr_contents());
399*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357644395000000LL, iter.start_time().to_microseconds());
400*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(1357644396000000LL, iter.end_time().to_microseconds());
401*b0d29bc4SBrooks Davis 
402*b0d29bc4SBrooks Davis     ++iter;
403*b0d29bc4SBrooks Davis     ATF_REQUIRE(!iter);
404*b0d29bc4SBrooks Davis }
405*b0d29bc4SBrooks Davis 
406*b0d29bc4SBrooks Davis 
407*b0d29bc4SBrooks Davis }  // anonymous namespace
408*b0d29bc4SBrooks Davis 
409*b0d29bc4SBrooks Davis 
410*b0d29bc4SBrooks Davis #define CURRENT_SCHEMA_TEST(dataset) \
411*b0d29bc4SBrooks Davis     ATF_TEST_CASE(current_schema_ ##dataset); \
412*b0d29bc4SBrooks Davis     ATF_TEST_CASE_HEAD(current_schema_ ##dataset) \
413*b0d29bc4SBrooks Davis     { \
414*b0d29bc4SBrooks Davis         logging::set_inmemory(); \
415*b0d29bc4SBrooks Davis         const std::string required_files = \
416*b0d29bc4SBrooks Davis             store::detail::schema_file().str() + " " + \
417*b0d29bc4SBrooks Davis             testdata_file("testdata_v3_" #dataset ".sql").str(); \
418*b0d29bc4SBrooks Davis         set_md_var("require.files", required_files); \
419*b0d29bc4SBrooks Davis     } \
420*b0d29bc4SBrooks Davis     ATF_TEST_CASE_BODY(current_schema_ ##dataset) \
421*b0d29bc4SBrooks Davis     { \
422*b0d29bc4SBrooks Davis         const fs::path testpath("test.db"); \
423*b0d29bc4SBrooks Davis         \
424*b0d29bc4SBrooks Davis         sqlite::database db = sqlite::database::open( \
425*b0d29bc4SBrooks Davis             testpath, sqlite::open_readwrite | sqlite::open_create); \
426*b0d29bc4SBrooks Davis         db.exec(utils::read_file(store::detail::schema_file())); \
427*b0d29bc4SBrooks Davis         db.exec(utils::read_file(testdata_file(\
428*b0d29bc4SBrooks Davis             "testdata_v3_" #dataset ".sql"))); \
429*b0d29bc4SBrooks Davis         db.close(); \
430*b0d29bc4SBrooks Davis         \
431*b0d29bc4SBrooks Davis         check_action_ ## dataset (testpath); \
432*b0d29bc4SBrooks Davis     }
433*b0d29bc4SBrooks Davis CURRENT_SCHEMA_TEST(1);
434*b0d29bc4SBrooks Davis CURRENT_SCHEMA_TEST(2);
435*b0d29bc4SBrooks Davis CURRENT_SCHEMA_TEST(3);
436*b0d29bc4SBrooks Davis CURRENT_SCHEMA_TEST(4);
437*b0d29bc4SBrooks Davis 
438*b0d29bc4SBrooks Davis 
439*b0d29bc4SBrooks Davis #define MIGRATE_SCHEMA_TEST(from_version) \
440*b0d29bc4SBrooks Davis     ATF_TEST_CASE(migrate_schema__from_v ##from_version); \
441*b0d29bc4SBrooks Davis     ATF_TEST_CASE_HEAD(migrate_schema__from_v ##from_version) \
442*b0d29bc4SBrooks Davis     { \
443*b0d29bc4SBrooks Davis         logging::set_inmemory(); \
444*b0d29bc4SBrooks Davis         \
445*b0d29bc4SBrooks Davis         const char* schema = "schema_v" #from_version ".sql"; \
446*b0d29bc4SBrooks Davis         const char* testdata = "testdata_v" #from_version ".sql"; \
447*b0d29bc4SBrooks Davis         \
448*b0d29bc4SBrooks Davis         std::string required_files = \
449*b0d29bc4SBrooks Davis             testdata_file(schema).str() + " " + testdata_file(testdata).str(); \
450*b0d29bc4SBrooks Davis         for (int i = from_version; i < store::detail::current_schema_version; \
451*b0d29bc4SBrooks Davis              ++i) \
452*b0d29bc4SBrooks Davis             required_files += " " + store::detail::migration_file( \
453*b0d29bc4SBrooks Davis                 i, i + 1).str(); \
454*b0d29bc4SBrooks Davis         \
455*b0d29bc4SBrooks Davis         set_md_var("require.files", required_files); \
456*b0d29bc4SBrooks Davis     } \
457*b0d29bc4SBrooks Davis     ATF_TEST_CASE_BODY(migrate_schema__from_v ##from_version) \
458*b0d29bc4SBrooks Davis     { \
459*b0d29bc4SBrooks Davis         const char* schema = "schema_v" #from_version ".sql"; \
460*b0d29bc4SBrooks Davis         const char* testdata = "testdata_v" #from_version ".sql"; \
461*b0d29bc4SBrooks Davis         \
462*b0d29bc4SBrooks Davis         const fs::path testpath("test.db"); \
463*b0d29bc4SBrooks Davis         \
464*b0d29bc4SBrooks Davis         sqlite::database db = sqlite::database::open( \
465*b0d29bc4SBrooks Davis             testpath, sqlite::open_readwrite | sqlite::open_create); \
466*b0d29bc4SBrooks Davis         db.exec(utils::read_file(testdata_file(schema))); \
467*b0d29bc4SBrooks Davis         db.exec(utils::read_file(testdata_file(testdata))); \
468*b0d29bc4SBrooks Davis         db.close(); \
469*b0d29bc4SBrooks Davis         \
470*b0d29bc4SBrooks Davis         store::migrate_schema(fs::path("test.db")); \
471*b0d29bc4SBrooks Davis         \
472*b0d29bc4SBrooks Davis         check_action_2(fs::path(".kyua/store/" \
473*b0d29bc4SBrooks Davis             "results.test_suite_root.20130108-111331-000000.db")); \
474*b0d29bc4SBrooks Davis         check_action_3(fs::path(".kyua/store/" \
475*b0d29bc4SBrooks Davis             "results.usr_tests.20130108-123832-000000.db")); \
476*b0d29bc4SBrooks Davis         check_action_4(fs::path(".kyua/store/" \
477*b0d29bc4SBrooks Davis             "results.usr_tests.20130108-112635-000000.db")); \
478*b0d29bc4SBrooks Davis     }
479*b0d29bc4SBrooks Davis MIGRATE_SCHEMA_TEST(1);
480*b0d29bc4SBrooks Davis MIGRATE_SCHEMA_TEST(2);
481*b0d29bc4SBrooks Davis 
482*b0d29bc4SBrooks Davis 
ATF_INIT_TEST_CASES(tcs)483*b0d29bc4SBrooks Davis ATF_INIT_TEST_CASES(tcs)
484*b0d29bc4SBrooks Davis {
485*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, current_schema_1);
486*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, current_schema_2);
487*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, current_schema_3);
488*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, current_schema_4);
489*b0d29bc4SBrooks Davis 
490*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, migrate_schema__from_v1);
491*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, migrate_schema__from_v2);
492*b0d29bc4SBrooks Davis }
493