xref: /freebsd/contrib/kyua/drivers/report_junit_test.cpp (revision 257e70f1d5ee61037c8c59b116538d3b6b1427a2)
1b0d29bc4SBrooks Davis // Copyright 2014 The Kyua Authors.
2b0d29bc4SBrooks Davis // All rights reserved.
3b0d29bc4SBrooks Davis //
4b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without
5b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are
6b0d29bc4SBrooks Davis // met:
7b0d29bc4SBrooks Davis //
8b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright
9b0d29bc4SBrooks Davis //   notice, this list of conditions and the following disclaimer.
10b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
11b0d29bc4SBrooks Davis //   notice, this list of conditions and the following disclaimer in the
12b0d29bc4SBrooks Davis //   documentation and/or other materials provided with the distribution.
13b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
14b0d29bc4SBrooks Davis //   may be used to endorse or promote products derived from this software
15b0d29bc4SBrooks Davis //   without specific prior written permission.
16b0d29bc4SBrooks Davis //
17b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28b0d29bc4SBrooks Davis 
29b0d29bc4SBrooks Davis #include "drivers/report_junit.hpp"
30b0d29bc4SBrooks Davis 
31b0d29bc4SBrooks Davis #include <sstream>
32b0d29bc4SBrooks Davis #include <vector>
33b0d29bc4SBrooks Davis 
34b0d29bc4SBrooks Davis #include <atf-c++.hpp>
35b0d29bc4SBrooks Davis 
36b0d29bc4SBrooks Davis #include "drivers/scan_results.hpp"
37b0d29bc4SBrooks Davis #include "engine/filters.hpp"
38b0d29bc4SBrooks Davis #include "model/context.hpp"
39b0d29bc4SBrooks Davis #include "model/metadata.hpp"
40b0d29bc4SBrooks Davis #include "model/test_case.hpp"
41b0d29bc4SBrooks Davis #include "model/test_program.hpp"
42b0d29bc4SBrooks Davis #include "model/test_result.hpp"
43b0d29bc4SBrooks Davis #include "store/write_backend.hpp"
44b0d29bc4SBrooks Davis #include "store/write_transaction.hpp"
45b0d29bc4SBrooks Davis #include "utils/datetime.hpp"
46b0d29bc4SBrooks Davis #include "utils/format/macros.hpp"
47b0d29bc4SBrooks Davis #include "utils/fs/path.hpp"
48b0d29bc4SBrooks Davis #include "utils/optional.ipp"
49b0d29bc4SBrooks Davis #include "utils/units.hpp"
50b0d29bc4SBrooks Davis 
51b0d29bc4SBrooks Davis namespace datetime = utils::datetime;
52b0d29bc4SBrooks Davis namespace fs = utils::fs;
53b0d29bc4SBrooks Davis namespace units = utils::units;
54b0d29bc4SBrooks Davis 
55b0d29bc4SBrooks Davis using utils::none;
56b0d29bc4SBrooks Davis 
57b0d29bc4SBrooks Davis 
58b0d29bc4SBrooks Davis namespace {
59b0d29bc4SBrooks Davis 
60b0d29bc4SBrooks Davis 
61b0d29bc4SBrooks Davis /// Formatted metadata for a test case with defaults.
62b0d29bc4SBrooks Davis static const char* const default_metadata =
63b0d29bc4SBrooks Davis     "allowed_architectures is empty\n"
64b0d29bc4SBrooks Davis     "allowed_platforms is empty\n"
65b0d29bc4SBrooks Davis     "description is empty\n"
66*257e70f1SIgor Ostapenko     "execenv is empty\n"
67*257e70f1SIgor Ostapenko     "execenv_jail_params is empty\n"
68b0d29bc4SBrooks Davis     "has_cleanup = false\n"
69b0d29bc4SBrooks Davis     "is_exclusive = false\n"
70b0d29bc4SBrooks Davis     "required_configs is empty\n"
71b0d29bc4SBrooks Davis     "required_disk_space = 0\n"
72b0d29bc4SBrooks Davis     "required_files is empty\n"
73b0d29bc4SBrooks Davis     "required_memory = 0\n"
74b0d29bc4SBrooks Davis     "required_programs is empty\n"
75b0d29bc4SBrooks Davis     "required_user is empty\n"
76b0d29bc4SBrooks Davis     "timeout = 300\n";
77b0d29bc4SBrooks Davis 
78b0d29bc4SBrooks Davis 
79b0d29bc4SBrooks Davis /// Formatted metadata for a test case constructed with the "with_metadata" flag
80b0d29bc4SBrooks Davis /// set to true in add_tests.
81b0d29bc4SBrooks Davis static const char* const overriden_metadata =
82b0d29bc4SBrooks Davis     "allowed_architectures is empty\n"
83b0d29bc4SBrooks Davis     "allowed_platforms is empty\n"
84b0d29bc4SBrooks Davis     "description = Textual description\n"
85*257e70f1SIgor Ostapenko     "execenv is empty\n"
86*257e70f1SIgor Ostapenko     "execenv_jail_params is empty\n"
87b0d29bc4SBrooks Davis     "has_cleanup = false\n"
88b0d29bc4SBrooks Davis     "is_exclusive = false\n"
89b0d29bc4SBrooks Davis     "required_configs is empty\n"
90b0d29bc4SBrooks Davis     "required_disk_space = 0\n"
91b0d29bc4SBrooks Davis     "required_files is empty\n"
92b0d29bc4SBrooks Davis     "required_memory = 0\n"
93b0d29bc4SBrooks Davis     "required_programs is empty\n"
94b0d29bc4SBrooks Davis     "required_user is empty\n"
95b0d29bc4SBrooks Davis     "timeout = 5678\n";
96b0d29bc4SBrooks Davis 
97b0d29bc4SBrooks Davis 
98b0d29bc4SBrooks Davis /// Populates the context of the given database.
99b0d29bc4SBrooks Davis ///
100b0d29bc4SBrooks Davis /// \param tx Transaction to use for the writes to the database.
101b0d29bc4SBrooks Davis /// \param env_vars Number of environment variables to add to the context.
102b0d29bc4SBrooks Davis static void
add_context(store::write_transaction & tx,const std::size_t env_vars)103b0d29bc4SBrooks Davis add_context(store::write_transaction& tx, const std::size_t env_vars)
104b0d29bc4SBrooks Davis {
105b0d29bc4SBrooks Davis     std::map< std::string, std::string > env;
106b0d29bc4SBrooks Davis     for (std::size_t i = 0; i < env_vars; i++)
107b0d29bc4SBrooks Davis         env[F("VAR%s") % i] = F("Value %s") % i;
108b0d29bc4SBrooks Davis     const model::context context(fs::path("/root"), env);
109b0d29bc4SBrooks Davis     (void)tx.put_context(context);
110b0d29bc4SBrooks Davis }
111b0d29bc4SBrooks Davis 
112b0d29bc4SBrooks Davis 
113b0d29bc4SBrooks Davis /// Adds a new test program with various test cases to the given database.
114b0d29bc4SBrooks Davis ///
115b0d29bc4SBrooks Davis /// \param tx Transaction to use for the writes to the database.
116b0d29bc4SBrooks Davis /// \param prog Test program name.
117b0d29bc4SBrooks Davis /// \param results Collection of results for the added test cases.  The size of
118b0d29bc4SBrooks Davis ///     this vector indicates the number of tests in the test program.
119b0d29bc4SBrooks Davis /// \param with_metadata Whether to add metadata overrides to the test cases.
120b0d29bc4SBrooks Davis /// \param with_output Whether to add stdout/stderr messages to the test cases.
121b0d29bc4SBrooks Davis static void
add_tests(store::write_transaction & tx,const char * prog,const std::vector<model::test_result> & results,const bool with_metadata,const bool with_output)122b0d29bc4SBrooks Davis add_tests(store::write_transaction& tx,
123b0d29bc4SBrooks Davis           const char* prog,
124b0d29bc4SBrooks Davis           const std::vector< model::test_result >& results,
125b0d29bc4SBrooks Davis           const bool with_metadata, const bool with_output)
126b0d29bc4SBrooks Davis {
127b0d29bc4SBrooks Davis     model::test_program_builder test_program_builder(
128b0d29bc4SBrooks Davis         "plain", fs::path(prog), fs::path("/root"), "suite");
129b0d29bc4SBrooks Davis 
130b0d29bc4SBrooks Davis     for (std::size_t j = 0; j < results.size(); j++) {
131b0d29bc4SBrooks Davis         model::metadata_builder builder;
132b0d29bc4SBrooks Davis         if (with_metadata) {
133b0d29bc4SBrooks Davis             builder.set_description("Textual description");
134b0d29bc4SBrooks Davis             builder.set_timeout(datetime::delta(5678, 0));
135b0d29bc4SBrooks Davis         }
136b0d29bc4SBrooks Davis         test_program_builder.add_test_case(F("t%s") % j, builder.build());
137b0d29bc4SBrooks Davis     }
138b0d29bc4SBrooks Davis 
139b0d29bc4SBrooks Davis     const model::test_program test_program = test_program_builder.build();
140b0d29bc4SBrooks Davis     const int64_t tp_id = tx.put_test_program(test_program);
141b0d29bc4SBrooks Davis 
142b0d29bc4SBrooks Davis     for (std::size_t j = 0; j < results.size(); j++) {
143b0d29bc4SBrooks Davis         const int64_t tc_id = tx.put_test_case(test_program, F("t%s") % j,
144b0d29bc4SBrooks Davis                                                tp_id);
145b0d29bc4SBrooks Davis         const datetime::timestamp start =
146b0d29bc4SBrooks Davis             datetime::timestamp::from_microseconds(0);
147b0d29bc4SBrooks Davis         const datetime::timestamp end =
148b0d29bc4SBrooks Davis             datetime::timestamp::from_microseconds(j * 1000000 + 500000);
149b0d29bc4SBrooks Davis         tx.put_result(results[j], tc_id, start, end);
150b0d29bc4SBrooks Davis 
151b0d29bc4SBrooks Davis         if (with_output) {
152b0d29bc4SBrooks Davis             atf::utils::create_file("fake-out", F("stdout file %s") % j);
153b0d29bc4SBrooks Davis             tx.put_test_case_file("__STDOUT__", fs::path("fake-out"), tc_id);
154b0d29bc4SBrooks Davis             atf::utils::create_file("fake-err", F("stderr file %s") % j);
155b0d29bc4SBrooks Davis             tx.put_test_case_file("__STDERR__", fs::path("fake-err"), tc_id);
156b0d29bc4SBrooks Davis         }
157b0d29bc4SBrooks Davis     }
158b0d29bc4SBrooks Davis }
159b0d29bc4SBrooks Davis 
160b0d29bc4SBrooks Davis 
161b0d29bc4SBrooks Davis }  // anonymous namespace
162b0d29bc4SBrooks Davis 
163b0d29bc4SBrooks Davis 
164b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(junit_classname);
ATF_TEST_CASE_BODY(junit_classname)165b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(junit_classname)
166b0d29bc4SBrooks Davis {
167b0d29bc4SBrooks Davis     const model::test_program test_program = model::test_program_builder(
168b0d29bc4SBrooks Davis         "plain", fs::path("dir1/dir2/program"), fs::path("/root"), "suite")
169b0d29bc4SBrooks Davis         .build();
170b0d29bc4SBrooks Davis 
171b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("dir1.dir2.program", drivers::junit_classname(test_program));
172b0d29bc4SBrooks Davis }
173b0d29bc4SBrooks Davis 
174b0d29bc4SBrooks Davis 
175b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(junit_duration);
ATF_TEST_CASE_BODY(junit_duration)176b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(junit_duration)
177b0d29bc4SBrooks Davis {
178b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("0.457",
179b0d29bc4SBrooks Davis                    drivers::junit_duration(datetime::delta(0, 456700)));
180b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("3.120",
181b0d29bc4SBrooks Davis                    drivers::junit_duration(datetime::delta(3, 120000)));
182b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ("5.000", drivers::junit_duration(datetime::delta(5, 0)));
183b0d29bc4SBrooks Davis }
184b0d29bc4SBrooks Davis 
185b0d29bc4SBrooks Davis 
186b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(junit_metadata__defaults);
ATF_TEST_CASE_BODY(junit_metadata__defaults)187b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(junit_metadata__defaults)
188b0d29bc4SBrooks Davis {
189b0d29bc4SBrooks Davis     const model::metadata metadata = model::metadata_builder().build();
190b0d29bc4SBrooks Davis 
191b0d29bc4SBrooks Davis     const std::string expected = std::string()
192b0d29bc4SBrooks Davis         + drivers::junit_metadata_header
193b0d29bc4SBrooks Davis         + default_metadata;
194b0d29bc4SBrooks Davis 
195b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(expected, drivers::junit_metadata(metadata));
196b0d29bc4SBrooks Davis }
197b0d29bc4SBrooks Davis 
198b0d29bc4SBrooks Davis 
199b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(junit_metadata__overrides);
ATF_TEST_CASE_BODY(junit_metadata__overrides)200b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(junit_metadata__overrides)
201b0d29bc4SBrooks Davis {
202b0d29bc4SBrooks Davis     const model::metadata metadata = model::metadata_builder()
203b0d29bc4SBrooks Davis         .add_allowed_architecture("arch1")
204b0d29bc4SBrooks Davis         .add_allowed_platform("platform1")
205b0d29bc4SBrooks Davis         .set_description("This is a test")
206*257e70f1SIgor Ostapenko         .set_execenv("jail")
207*257e70f1SIgor Ostapenko         .set_execenv_jail_params("vnet")
208b0d29bc4SBrooks Davis         .set_has_cleanup(true)
209b0d29bc4SBrooks Davis         .set_is_exclusive(true)
210b0d29bc4SBrooks Davis         .add_required_config("config1")
211b0d29bc4SBrooks Davis         .set_required_disk_space(units::bytes(456))
212b0d29bc4SBrooks Davis         .add_required_file(fs::path("file1"))
213b0d29bc4SBrooks Davis         .set_required_memory(units::bytes(123))
214b0d29bc4SBrooks Davis         .add_required_program(fs::path("prog1"))
215b0d29bc4SBrooks Davis         .set_required_user("root")
216b0d29bc4SBrooks Davis         .set_timeout(datetime::delta(10, 0))
217b0d29bc4SBrooks Davis         .build();
218b0d29bc4SBrooks Davis 
219b0d29bc4SBrooks Davis     const std::string expected = std::string()
220b0d29bc4SBrooks Davis         + drivers::junit_metadata_header
221b0d29bc4SBrooks Davis         + "allowed_architectures = arch1\n"
222b0d29bc4SBrooks Davis         + "allowed_platforms = platform1\n"
223b0d29bc4SBrooks Davis         + "description = This is a test\n"
224*257e70f1SIgor Ostapenko         + "execenv = jail\n"
225*257e70f1SIgor Ostapenko         + "execenv_jail_params = vnet\n"
226b0d29bc4SBrooks Davis         + "has_cleanup = true\n"
227b0d29bc4SBrooks Davis         + "is_exclusive = true\n"
228b0d29bc4SBrooks Davis         + "required_configs = config1\n"
229b0d29bc4SBrooks Davis         + "required_disk_space = 456\n"
230b0d29bc4SBrooks Davis         + "required_files = file1\n"
231b0d29bc4SBrooks Davis         + "required_memory = 123\n"
232b0d29bc4SBrooks Davis         + "required_programs = prog1\n"
233b0d29bc4SBrooks Davis         + "required_user = root\n"
234b0d29bc4SBrooks Davis         + "timeout = 10\n";
235b0d29bc4SBrooks Davis 
236b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(expected, drivers::junit_metadata(metadata));
237b0d29bc4SBrooks Davis }
238b0d29bc4SBrooks Davis 
239b0d29bc4SBrooks Davis 
240b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(junit_timing);
ATF_TEST_CASE_BODY(junit_timing)241b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(junit_timing)
242b0d29bc4SBrooks Davis {
243b0d29bc4SBrooks Davis     const std::string expected = std::string()
244b0d29bc4SBrooks Davis         + drivers::junit_timing_header +
245b0d29bc4SBrooks Davis         "Start time: 2015-06-12T01:02:35.123456Z\n"
246b0d29bc4SBrooks Davis         "End time:   2016-07-13T18:47:10.000001Z\n"
247b0d29bc4SBrooks Davis         "Duration:   34364674.877s\n";
248b0d29bc4SBrooks Davis 
249b0d29bc4SBrooks Davis     const datetime::timestamp start_time =
250b0d29bc4SBrooks Davis         datetime::timestamp::from_values(2015, 6, 12, 1, 2, 35, 123456);
251b0d29bc4SBrooks Davis     const datetime::timestamp end_time =
252b0d29bc4SBrooks Davis         datetime::timestamp::from_values(2016, 7, 13, 18, 47, 10, 1);
253b0d29bc4SBrooks Davis 
254b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(expected, drivers::junit_timing(start_time, end_time));
255b0d29bc4SBrooks Davis }
256b0d29bc4SBrooks Davis 
257b0d29bc4SBrooks Davis 
258b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(report_junit_hooks__minimal);
ATF_TEST_CASE_BODY(report_junit_hooks__minimal)259b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(report_junit_hooks__minimal)
260b0d29bc4SBrooks Davis {
261b0d29bc4SBrooks Davis     store::write_backend backend = store::write_backend::open_rw(
262b0d29bc4SBrooks Davis         fs::path("test.db"));
263b0d29bc4SBrooks Davis     store::write_transaction tx = backend.start_write();
264b0d29bc4SBrooks Davis     add_context(tx, 0);
265b0d29bc4SBrooks Davis     tx.commit();
266b0d29bc4SBrooks Davis     backend.close();
267b0d29bc4SBrooks Davis 
268b0d29bc4SBrooks Davis     std::ostringstream output;
269b0d29bc4SBrooks Davis 
270b0d29bc4SBrooks Davis     drivers::report_junit_hooks hooks(output);
271b0d29bc4SBrooks Davis     drivers::scan_results::drive(fs::path("test.db"),
272b0d29bc4SBrooks Davis                                  std::set< engine::test_filter >(),
273b0d29bc4SBrooks Davis                                  hooks);
274b0d29bc4SBrooks Davis 
275b0d29bc4SBrooks Davis     const char* expected =
276b0d29bc4SBrooks Davis         "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
277b0d29bc4SBrooks Davis         "<testsuite>\n"
278b0d29bc4SBrooks Davis         "<properties>\n"
279b0d29bc4SBrooks Davis         "<property name=\"cwd\" value=\"/root\"/>\n"
280b0d29bc4SBrooks Davis         "</properties>\n"
281b0d29bc4SBrooks Davis         "</testsuite>\n";
282b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(expected, output.str());
283b0d29bc4SBrooks Davis }
284b0d29bc4SBrooks Davis 
285b0d29bc4SBrooks Davis 
286b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(report_junit_hooks__some_tests);
ATF_TEST_CASE_BODY(report_junit_hooks__some_tests)287b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(report_junit_hooks__some_tests)
288b0d29bc4SBrooks Davis {
289b0d29bc4SBrooks Davis     std::vector< model::test_result > results1;
290b0d29bc4SBrooks Davis     results1.push_back(model::test_result(
291b0d29bc4SBrooks Davis         model::test_result_broken, "Broken"));
292b0d29bc4SBrooks Davis     results1.push_back(model::test_result(
293b0d29bc4SBrooks Davis         model::test_result_expected_failure, "XFail"));
294b0d29bc4SBrooks Davis     results1.push_back(model::test_result(
295b0d29bc4SBrooks Davis         model::test_result_failed, "Failed"));
296b0d29bc4SBrooks Davis     std::vector< model::test_result > results2;
297b0d29bc4SBrooks Davis     results2.push_back(model::test_result(
298b0d29bc4SBrooks Davis         model::test_result_passed));
299b0d29bc4SBrooks Davis     results2.push_back(model::test_result(
300b0d29bc4SBrooks Davis         model::test_result_skipped, "Skipped"));
301b0d29bc4SBrooks Davis 
302b0d29bc4SBrooks Davis     store::write_backend backend = store::write_backend::open_rw(
303b0d29bc4SBrooks Davis         fs::path("test.db"));
304b0d29bc4SBrooks Davis     store::write_transaction tx = backend.start_write();
305b0d29bc4SBrooks Davis     add_context(tx, 2);
306b0d29bc4SBrooks Davis     add_tests(tx, "dir/prog-1", results1, false, false);
307b0d29bc4SBrooks Davis     add_tests(tx, "dir/sub/prog-2", results2, true, true);
308b0d29bc4SBrooks Davis     tx.commit();
309b0d29bc4SBrooks Davis     backend.close();
310b0d29bc4SBrooks Davis 
311b0d29bc4SBrooks Davis     std::ostringstream output;
312b0d29bc4SBrooks Davis 
313b0d29bc4SBrooks Davis     drivers::report_junit_hooks hooks(output);
314b0d29bc4SBrooks Davis     drivers::scan_results::drive(fs::path("test.db"),
315b0d29bc4SBrooks Davis                                  std::set< engine::test_filter >(),
316b0d29bc4SBrooks Davis                                  hooks);
317b0d29bc4SBrooks Davis 
318b0d29bc4SBrooks Davis     const std::string expected = std::string() +
319b0d29bc4SBrooks Davis         "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
320b0d29bc4SBrooks Davis         "<testsuite>\n"
321b0d29bc4SBrooks Davis         "<properties>\n"
322b0d29bc4SBrooks Davis         "<property name=\"cwd\" value=\"/root\"/>\n"
323b0d29bc4SBrooks Davis         "<property name=\"env.VAR0\" value=\"Value 0\"/>\n"
324b0d29bc4SBrooks Davis         "<property name=\"env.VAR1\" value=\"Value 1\"/>\n"
325b0d29bc4SBrooks Davis         "</properties>\n"
326b0d29bc4SBrooks Davis 
327b0d29bc4SBrooks Davis         "<testcase classname=\"dir.prog-1\" name=\"t0\" time=\"0.500\">\n"
328b0d29bc4SBrooks Davis         "<error message=\"Broken\"/>\n"
329b0d29bc4SBrooks Davis         "<system-err>"
330b0d29bc4SBrooks Davis         + drivers::junit_metadata_header +
331b0d29bc4SBrooks Davis         default_metadata
332b0d29bc4SBrooks Davis         + drivers::junit_timing_header +
333b0d29bc4SBrooks Davis         "Start time: 1970-01-01T00:00:00.000000Z\n"
334b0d29bc4SBrooks Davis         "End time:   1970-01-01T00:00:00.500000Z\n"
335b0d29bc4SBrooks Davis         "Duration:   0.500s\n"
336b0d29bc4SBrooks Davis         + drivers::junit_stderr_header +
337b0d29bc4SBrooks Davis         "&lt;EMPTY&gt;\n"
338b0d29bc4SBrooks Davis         "</system-err>\n"
339b0d29bc4SBrooks Davis         "</testcase>\n"
340b0d29bc4SBrooks Davis 
341b0d29bc4SBrooks Davis         "<testcase classname=\"dir.prog-1\" name=\"t1\" time=\"1.500\">\n"
342b0d29bc4SBrooks Davis         "<system-err>"
343b0d29bc4SBrooks Davis         "Expected failure result details\n"
344b0d29bc4SBrooks Davis         "-------------------------------\n"
345b0d29bc4SBrooks Davis         "\n"
346b0d29bc4SBrooks Davis         "XFail\n"
347b0d29bc4SBrooks Davis         "\n"
348b0d29bc4SBrooks Davis         + drivers::junit_metadata_header +
349b0d29bc4SBrooks Davis         default_metadata
350b0d29bc4SBrooks Davis         + drivers::junit_timing_header +
351b0d29bc4SBrooks Davis         "Start time: 1970-01-01T00:00:00.000000Z\n"
352b0d29bc4SBrooks Davis         "End time:   1970-01-01T00:00:01.500000Z\n"
353b0d29bc4SBrooks Davis         "Duration:   1.500s\n"
354b0d29bc4SBrooks Davis         + drivers::junit_stderr_header +
355b0d29bc4SBrooks Davis         "&lt;EMPTY&gt;\n"
356b0d29bc4SBrooks Davis         "</system-err>\n"
357b0d29bc4SBrooks Davis         "</testcase>\n"
358b0d29bc4SBrooks Davis 
359b0d29bc4SBrooks Davis         "<testcase classname=\"dir.prog-1\" name=\"t2\" time=\"2.500\">\n"
360b0d29bc4SBrooks Davis         "<failure message=\"Failed\"/>\n"
361b0d29bc4SBrooks Davis         "<system-err>"
362b0d29bc4SBrooks Davis         + drivers::junit_metadata_header +
363b0d29bc4SBrooks Davis         default_metadata
364b0d29bc4SBrooks Davis         + drivers::junit_timing_header +
365b0d29bc4SBrooks Davis         "Start time: 1970-01-01T00:00:00.000000Z\n"
366b0d29bc4SBrooks Davis         "End time:   1970-01-01T00:00:02.500000Z\n"
367b0d29bc4SBrooks Davis         "Duration:   2.500s\n"
368b0d29bc4SBrooks Davis         +  drivers::junit_stderr_header +
369b0d29bc4SBrooks Davis         "&lt;EMPTY&gt;\n"
370b0d29bc4SBrooks Davis         "</system-err>\n"
371b0d29bc4SBrooks Davis         "</testcase>\n"
372b0d29bc4SBrooks Davis 
373b0d29bc4SBrooks Davis         "<testcase classname=\"dir.sub.prog-2\" name=\"t0\" time=\"0.500\">\n"
374b0d29bc4SBrooks Davis         "<system-out>stdout file 0</system-out>\n"
375b0d29bc4SBrooks Davis         "<system-err>"
376b0d29bc4SBrooks Davis         + drivers::junit_metadata_header +
377b0d29bc4SBrooks Davis         overriden_metadata
378b0d29bc4SBrooks Davis         + drivers::junit_timing_header +
379b0d29bc4SBrooks Davis         "Start time: 1970-01-01T00:00:00.000000Z\n"
380b0d29bc4SBrooks Davis         "End time:   1970-01-01T00:00:00.500000Z\n"
381b0d29bc4SBrooks Davis         "Duration:   0.500s\n"
382b0d29bc4SBrooks Davis         + drivers::junit_stderr_header +
383b0d29bc4SBrooks Davis         "stderr file 0</system-err>\n"
384b0d29bc4SBrooks Davis         "</testcase>\n"
385b0d29bc4SBrooks Davis 
386b0d29bc4SBrooks Davis         "<testcase classname=\"dir.sub.prog-2\" name=\"t1\" time=\"1.500\">\n"
387b0d29bc4SBrooks Davis         "<skipped/>\n"
388b0d29bc4SBrooks Davis         "<system-out>stdout file 1</system-out>\n"
389b0d29bc4SBrooks Davis         "<system-err>"
390b0d29bc4SBrooks Davis         "Skipped result details\n"
391b0d29bc4SBrooks Davis         "----------------------\n"
392b0d29bc4SBrooks Davis         "\n"
393b0d29bc4SBrooks Davis         "Skipped\n"
394b0d29bc4SBrooks Davis         "\n"
395b0d29bc4SBrooks Davis         + drivers::junit_metadata_header +
396b0d29bc4SBrooks Davis         overriden_metadata
397b0d29bc4SBrooks Davis         + drivers::junit_timing_header +
398b0d29bc4SBrooks Davis         "Start time: 1970-01-01T00:00:00.000000Z\n"
399b0d29bc4SBrooks Davis         "End time:   1970-01-01T00:00:01.500000Z\n"
400b0d29bc4SBrooks Davis         "Duration:   1.500s\n"
401b0d29bc4SBrooks Davis         + drivers::junit_stderr_header +
402b0d29bc4SBrooks Davis         "stderr file 1</system-err>\n"
403b0d29bc4SBrooks Davis         "</testcase>\n"
404b0d29bc4SBrooks Davis 
405b0d29bc4SBrooks Davis         "</testsuite>\n";
406b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(expected, output.str());
407b0d29bc4SBrooks Davis }
408b0d29bc4SBrooks Davis 
409b0d29bc4SBrooks Davis 
ATF_INIT_TEST_CASES(tcs)410b0d29bc4SBrooks Davis ATF_INIT_TEST_CASES(tcs)
411b0d29bc4SBrooks Davis {
412b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, junit_classname);
413b0d29bc4SBrooks Davis 
414b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, junit_duration);
415b0d29bc4SBrooks Davis 
416b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, junit_metadata__defaults);
417b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, junit_metadata__overrides);
418b0d29bc4SBrooks Davis 
419b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, junit_timing);
420b0d29bc4SBrooks Davis 
421b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, report_junit_hooks__minimal);
422b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, report_junit_hooks__some_tests);
423b0d29bc4SBrooks Davis }
424