1*00b67f09SDavid van Moolenbroek //
2*00b67f09SDavid van Moolenbroek // Automated Testing Framework (atf)
3*00b67f09SDavid van Moolenbroek //
4*00b67f09SDavid van Moolenbroek // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*00b67f09SDavid van Moolenbroek // All rights reserved.
6*00b67f09SDavid van Moolenbroek //
7*00b67f09SDavid van Moolenbroek // Redistribution and use in source and binary forms, with or without
8*00b67f09SDavid van Moolenbroek // modification, are permitted provided that the following conditions
9*00b67f09SDavid van Moolenbroek // are met:
10*00b67f09SDavid van Moolenbroek // 1. Redistributions of source code must retain the above copyright
11*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer.
12*00b67f09SDavid van Moolenbroek // 2. Redistributions in binary form must reproduce the above copyright
13*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer in the
14*00b67f09SDavid van Moolenbroek // documentation and/or other materials provided with the distribution.
15*00b67f09SDavid van Moolenbroek //
16*00b67f09SDavid van Moolenbroek // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*00b67f09SDavid van Moolenbroek // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*00b67f09SDavid van Moolenbroek // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*00b67f09SDavid van Moolenbroek // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*00b67f09SDavid van Moolenbroek // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*00b67f09SDavid van Moolenbroek // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*00b67f09SDavid van Moolenbroek // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*00b67f09SDavid van Moolenbroek // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*00b67f09SDavid van Moolenbroek // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*00b67f09SDavid van Moolenbroek // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*00b67f09SDavid van Moolenbroek // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*00b67f09SDavid van Moolenbroek // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*00b67f09SDavid van Moolenbroek //
29*00b67f09SDavid van Moolenbroek
30*00b67f09SDavid van Moolenbroek extern "C" {
31*00b67f09SDavid van Moolenbroek #include <sys/time.h>
32*00b67f09SDavid van Moolenbroek }
33*00b67f09SDavid van Moolenbroek
34*00b67f09SDavid van Moolenbroek #include <map>
35*00b67f09SDavid van Moolenbroek #include <sstream>
36*00b67f09SDavid van Moolenbroek #include <utility>
37*00b67f09SDavid van Moolenbroek
38*00b67f09SDavid van Moolenbroek #include "atf-c/defs.h"
39*00b67f09SDavid van Moolenbroek
40*00b67f09SDavid van Moolenbroek #include "atf-c++/detail/parser.hpp"
41*00b67f09SDavid van Moolenbroek #include "atf-c++/detail/sanity.hpp"
42*00b67f09SDavid van Moolenbroek #include "atf-c++/detail/text.hpp"
43*00b67f09SDavid van Moolenbroek
44*00b67f09SDavid van Moolenbroek #include "reader.hpp"
45*00b67f09SDavid van Moolenbroek
46*00b67f09SDavid van Moolenbroek namespace impl = atf::atf_report;
47*00b67f09SDavid van Moolenbroek #define IMPL_NAME "atf::atf_report"
48*00b67f09SDavid van Moolenbroek
49*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
50*00b67f09SDavid van Moolenbroek // Auxiliary functions.
51*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
52*00b67f09SDavid van Moolenbroek
53*00b67f09SDavid van Moolenbroek template< typename Type >
54*00b67f09SDavid van Moolenbroek Type
string_to_int(const std::string & str)55*00b67f09SDavid van Moolenbroek string_to_int(const std::string& str)
56*00b67f09SDavid van Moolenbroek {
57*00b67f09SDavid van Moolenbroek std::istringstream ss(str);
58*00b67f09SDavid van Moolenbroek Type s;
59*00b67f09SDavid van Moolenbroek ss >> s;
60*00b67f09SDavid van Moolenbroek
61*00b67f09SDavid van Moolenbroek return s;
62*00b67f09SDavid van Moolenbroek }
63*00b67f09SDavid van Moolenbroek
64*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
65*00b67f09SDavid van Moolenbroek // The "atf_tps" auxiliary parser.
66*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
67*00b67f09SDavid van Moolenbroek
68*00b67f09SDavid van Moolenbroek namespace atf_tps {
69*00b67f09SDavid van Moolenbroek
70*00b67f09SDavid van Moolenbroek static const atf::parser::token_type eof_type = 0;
71*00b67f09SDavid van Moolenbroek static const atf::parser::token_type nl_type = 1;
72*00b67f09SDavid van Moolenbroek static const atf::parser::token_type text_type = 2;
73*00b67f09SDavid van Moolenbroek static const atf::parser::token_type colon_type = 3;
74*00b67f09SDavid van Moolenbroek static const atf::parser::token_type comma_type = 4;
75*00b67f09SDavid van Moolenbroek static const atf::parser::token_type tps_count_type = 5;
76*00b67f09SDavid van Moolenbroek static const atf::parser::token_type tp_start_type = 6;
77*00b67f09SDavid van Moolenbroek static const atf::parser::token_type tp_end_type = 7;
78*00b67f09SDavid van Moolenbroek static const atf::parser::token_type tc_start_type = 8;
79*00b67f09SDavid van Moolenbroek static const atf::parser::token_type tc_so_type = 9;
80*00b67f09SDavid van Moolenbroek static const atf::parser::token_type tc_se_type = 10;
81*00b67f09SDavid van Moolenbroek static const atf::parser::token_type tc_end_type = 11;
82*00b67f09SDavid van Moolenbroek static const atf::parser::token_type passed_type = 12;
83*00b67f09SDavid van Moolenbroek static const atf::parser::token_type failed_type = 13;
84*00b67f09SDavid van Moolenbroek static const atf::parser::token_type skipped_type = 14;
85*00b67f09SDavid van Moolenbroek static const atf::parser::token_type info_type = 16;
86*00b67f09SDavid van Moolenbroek static const atf::parser::token_type expected_death_type = 17;
87*00b67f09SDavid van Moolenbroek static const atf::parser::token_type expected_exit_type = 18;
88*00b67f09SDavid van Moolenbroek static const atf::parser::token_type expected_failure_type = 19;
89*00b67f09SDavid van Moolenbroek static const atf::parser::token_type expected_signal_type = 20;
90*00b67f09SDavid van Moolenbroek static const atf::parser::token_type expected_timeout_type = 21;
91*00b67f09SDavid van Moolenbroek
92*00b67f09SDavid van Moolenbroek class tokenizer : public atf::parser::tokenizer< std::istream > {
93*00b67f09SDavid van Moolenbroek public:
tokenizer(std::istream & is,size_t curline)94*00b67f09SDavid van Moolenbroek tokenizer(std::istream& is, size_t curline) :
95*00b67f09SDavid van Moolenbroek atf::parser::tokenizer< std::istream >
96*00b67f09SDavid van Moolenbroek (is, true, eof_type, nl_type, text_type, curline)
97*00b67f09SDavid van Moolenbroek {
98*00b67f09SDavid van Moolenbroek add_delim(':', colon_type);
99*00b67f09SDavid van Moolenbroek add_delim(',', comma_type);
100*00b67f09SDavid van Moolenbroek add_keyword("tps-count", tps_count_type);
101*00b67f09SDavid van Moolenbroek add_keyword("tp-start", tp_start_type);
102*00b67f09SDavid van Moolenbroek add_keyword("tp-end", tp_end_type);
103*00b67f09SDavid van Moolenbroek add_keyword("tc-start", tc_start_type);
104*00b67f09SDavid van Moolenbroek add_keyword("tc-so", tc_so_type);
105*00b67f09SDavid van Moolenbroek add_keyword("tc-se", tc_se_type);
106*00b67f09SDavid van Moolenbroek add_keyword("tc-end", tc_end_type);
107*00b67f09SDavid van Moolenbroek add_keyword("passed", passed_type);
108*00b67f09SDavid van Moolenbroek add_keyword("failed", failed_type);
109*00b67f09SDavid van Moolenbroek add_keyword("skipped", skipped_type);
110*00b67f09SDavid van Moolenbroek add_keyword("info", info_type);
111*00b67f09SDavid van Moolenbroek add_keyword("expected_death", expected_death_type);
112*00b67f09SDavid van Moolenbroek add_keyword("expected_exit", expected_exit_type);
113*00b67f09SDavid van Moolenbroek add_keyword("expected_failure", expected_failure_type);
114*00b67f09SDavid van Moolenbroek add_keyword("expected_signal", expected_signal_type);
115*00b67f09SDavid van Moolenbroek add_keyword("expected_timeout", expected_timeout_type);
116*00b67f09SDavid van Moolenbroek }
117*00b67f09SDavid van Moolenbroek };
118*00b67f09SDavid van Moolenbroek
119*00b67f09SDavid van Moolenbroek } // namespace atf_tps
120*00b67f09SDavid van Moolenbroek
121*00b67f09SDavid van Moolenbroek struct timeval
read_timeval(atf::parser::parser<atf_tps::tokenizer> & parser)122*00b67f09SDavid van Moolenbroek read_timeval(atf::parser::parser< atf_tps::tokenizer >& parser)
123*00b67f09SDavid van Moolenbroek {
124*00b67f09SDavid van Moolenbroek using namespace atf_tps;
125*00b67f09SDavid van Moolenbroek
126*00b67f09SDavid van Moolenbroek atf::parser::token t = parser.expect(text_type, "timestamp");
127*00b67f09SDavid van Moolenbroek const std::string::size_type divider = t.text().find('.');
128*00b67f09SDavid van Moolenbroek if (divider == std::string::npos || divider == 0 ||
129*00b67f09SDavid van Moolenbroek divider == t.text().length() - 1)
130*00b67f09SDavid van Moolenbroek throw atf::parser::parse_error(t.lineno(),
131*00b67f09SDavid van Moolenbroek "Malformed timestamp value " + t.text());
132*00b67f09SDavid van Moolenbroek
133*00b67f09SDavid van Moolenbroek struct timeval tv;
134*00b67f09SDavid van Moolenbroek tv.tv_sec = string_to_int< long >(t.text().substr(0, divider));
135*00b67f09SDavid van Moolenbroek tv.tv_usec = string_to_int< long >(t.text().substr(divider + 1));
136*00b67f09SDavid van Moolenbroek return tv;
137*00b67f09SDavid van Moolenbroek }
138*00b67f09SDavid van Moolenbroek
139*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
140*00b67f09SDavid van Moolenbroek // The "atf_tps_reader" class.
141*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
142*00b67f09SDavid van Moolenbroek
atf_tps_reader(std::istream & is)143*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::atf_tps_reader(std::istream& is) :
144*00b67f09SDavid van Moolenbroek m_is(is)
145*00b67f09SDavid van Moolenbroek {
146*00b67f09SDavid van Moolenbroek }
147*00b67f09SDavid van Moolenbroek
~atf_tps_reader(void)148*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::~atf_tps_reader(void)
149*00b67f09SDavid van Moolenbroek {
150*00b67f09SDavid van Moolenbroek }
151*00b67f09SDavid van Moolenbroek
152*00b67f09SDavid van Moolenbroek void
got_info(const std::string & what ATF_DEFS_ATTRIBUTE_UNUSED,const std::string & val ATF_DEFS_ATTRIBUTE_UNUSED)153*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_info(
154*00b67f09SDavid van Moolenbroek const std::string& what ATF_DEFS_ATTRIBUTE_UNUSED,
155*00b67f09SDavid van Moolenbroek const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED)
156*00b67f09SDavid van Moolenbroek {
157*00b67f09SDavid van Moolenbroek }
158*00b67f09SDavid van Moolenbroek
159*00b67f09SDavid van Moolenbroek void
got_ntps(size_t ntps ATF_DEFS_ATTRIBUTE_UNUSED)160*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_ntps(size_t ntps ATF_DEFS_ATTRIBUTE_UNUSED)
161*00b67f09SDavid van Moolenbroek {
162*00b67f09SDavid van Moolenbroek }
163*00b67f09SDavid van Moolenbroek
164*00b67f09SDavid van Moolenbroek void
got_tp_start(const std::string & tp ATF_DEFS_ATTRIBUTE_UNUSED,size_t ntcs ATF_DEFS_ATTRIBUTE_UNUSED)165*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_tp_start(
166*00b67f09SDavid van Moolenbroek const std::string& tp ATF_DEFS_ATTRIBUTE_UNUSED,
167*00b67f09SDavid van Moolenbroek size_t ntcs ATF_DEFS_ATTRIBUTE_UNUSED)
168*00b67f09SDavid van Moolenbroek {
169*00b67f09SDavid van Moolenbroek }
170*00b67f09SDavid van Moolenbroek
171*00b67f09SDavid van Moolenbroek void
got_tp_end(struct timeval * tv ATF_DEFS_ATTRIBUTE_UNUSED,const std::string & reason ATF_DEFS_ATTRIBUTE_UNUSED)172*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_tp_end(
173*00b67f09SDavid van Moolenbroek struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED,
174*00b67f09SDavid van Moolenbroek const std::string& reason ATF_DEFS_ATTRIBUTE_UNUSED)
175*00b67f09SDavid van Moolenbroek {
176*00b67f09SDavid van Moolenbroek }
177*00b67f09SDavid van Moolenbroek
178*00b67f09SDavid van Moolenbroek void
got_tc_start(const std::string & tcname ATF_DEFS_ATTRIBUTE_UNUSED)179*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_tc_start(
180*00b67f09SDavid van Moolenbroek const std::string& tcname ATF_DEFS_ATTRIBUTE_UNUSED)
181*00b67f09SDavid van Moolenbroek {
182*00b67f09SDavid van Moolenbroek }
183*00b67f09SDavid van Moolenbroek
184*00b67f09SDavid van Moolenbroek void
got_tc_stdout_line(const std::string & line ATF_DEFS_ATTRIBUTE_UNUSED)185*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_tc_stdout_line(
186*00b67f09SDavid van Moolenbroek const std::string& line ATF_DEFS_ATTRIBUTE_UNUSED)
187*00b67f09SDavid van Moolenbroek {
188*00b67f09SDavid van Moolenbroek }
189*00b67f09SDavid van Moolenbroek
190*00b67f09SDavid van Moolenbroek void
got_tc_stderr_line(const std::string & line ATF_DEFS_ATTRIBUTE_UNUSED)191*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_tc_stderr_line(
192*00b67f09SDavid van Moolenbroek const std::string& line ATF_DEFS_ATTRIBUTE_UNUSED)
193*00b67f09SDavid van Moolenbroek {
194*00b67f09SDavid van Moolenbroek }
195*00b67f09SDavid van Moolenbroek
196*00b67f09SDavid van Moolenbroek void
got_tc_end(const std::string & state ATF_DEFS_ATTRIBUTE_UNUSED,struct timeval * tv ATF_DEFS_ATTRIBUTE_UNUSED,const std::string & reason ATF_DEFS_ATTRIBUTE_UNUSED)197*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_tc_end(
198*00b67f09SDavid van Moolenbroek const std::string& state ATF_DEFS_ATTRIBUTE_UNUSED,
199*00b67f09SDavid van Moolenbroek struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED,
200*00b67f09SDavid van Moolenbroek const std::string& reason ATF_DEFS_ATTRIBUTE_UNUSED)
201*00b67f09SDavid van Moolenbroek {
202*00b67f09SDavid van Moolenbroek }
203*00b67f09SDavid van Moolenbroek
204*00b67f09SDavid van Moolenbroek void
got_eof(void)205*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::got_eof(void)
206*00b67f09SDavid van Moolenbroek {
207*00b67f09SDavid van Moolenbroek }
208*00b67f09SDavid van Moolenbroek
209*00b67f09SDavid van Moolenbroek void
read_info(void * pptr)210*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::read_info(void* pptr)
211*00b67f09SDavid van Moolenbroek {
212*00b67f09SDavid van Moolenbroek using atf::parser::parse_error;
213*00b67f09SDavid van Moolenbroek using namespace atf_tps;
214*00b67f09SDavid van Moolenbroek
215*00b67f09SDavid van Moolenbroek atf::parser::parser< tokenizer >& p =
216*00b67f09SDavid van Moolenbroek *reinterpret_cast< atf::parser::parser< tokenizer >* >
217*00b67f09SDavid van Moolenbroek (pptr);
218*00b67f09SDavid van Moolenbroek
219*00b67f09SDavid van Moolenbroek (void)p.expect(colon_type, "`:'");
220*00b67f09SDavid van Moolenbroek
221*00b67f09SDavid van Moolenbroek atf::parser::token t = p.expect(text_type, "info property name");
222*00b67f09SDavid van Moolenbroek (void)p.expect(comma_type, "`,'");
223*00b67f09SDavid van Moolenbroek got_info(t.text(), atf::text::trim(p.rest_of_line()));
224*00b67f09SDavid van Moolenbroek
225*00b67f09SDavid van Moolenbroek (void)p.expect(nl_type, "new line");
226*00b67f09SDavid van Moolenbroek }
227*00b67f09SDavid van Moolenbroek
228*00b67f09SDavid van Moolenbroek void
read_tp(void * pptr)229*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::read_tp(void* pptr)
230*00b67f09SDavid van Moolenbroek {
231*00b67f09SDavid van Moolenbroek using atf::parser::parse_error;
232*00b67f09SDavid van Moolenbroek using namespace atf_tps;
233*00b67f09SDavid van Moolenbroek
234*00b67f09SDavid van Moolenbroek atf::parser::parser< tokenizer >& p =
235*00b67f09SDavid van Moolenbroek *reinterpret_cast< atf::parser::parser< tokenizer >* >
236*00b67f09SDavid van Moolenbroek (pptr);
237*00b67f09SDavid van Moolenbroek
238*00b67f09SDavid van Moolenbroek atf::parser::token t = p.expect(tp_start_type,
239*00b67f09SDavid van Moolenbroek "start of test program");
240*00b67f09SDavid van Moolenbroek
241*00b67f09SDavid van Moolenbroek t = p.expect(colon_type, "`:'");
242*00b67f09SDavid van Moolenbroek
243*00b67f09SDavid van Moolenbroek struct timeval s1 = read_timeval(p);
244*00b67f09SDavid van Moolenbroek
245*00b67f09SDavid van Moolenbroek t = p.expect(comma_type, "`,'");
246*00b67f09SDavid van Moolenbroek
247*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "test program name");
248*00b67f09SDavid van Moolenbroek std::string tpname = t.text();
249*00b67f09SDavid van Moolenbroek
250*00b67f09SDavid van Moolenbroek t = p.expect(comma_type, "`,'");
251*00b67f09SDavid van Moolenbroek
252*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "number of test programs");
253*00b67f09SDavid van Moolenbroek size_t ntcs = string_to_int< std::size_t >(t.text());
254*00b67f09SDavid van Moolenbroek
255*00b67f09SDavid van Moolenbroek t = p.expect(nl_type, "new line");
256*00b67f09SDavid van Moolenbroek
257*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_tp_start(tpname, ntcs));
258*00b67f09SDavid van Moolenbroek
259*00b67f09SDavid van Moolenbroek size_t i = 0;
260*00b67f09SDavid van Moolenbroek while (p.good() && i < ntcs) {
261*00b67f09SDavid van Moolenbroek try {
262*00b67f09SDavid van Moolenbroek read_tc(&p);
263*00b67f09SDavid van Moolenbroek i++;
264*00b67f09SDavid van Moolenbroek } catch (const parse_error& pe) {
265*00b67f09SDavid van Moolenbroek p.add_error(pe);
266*00b67f09SDavid van Moolenbroek p.reset(nl_type);
267*00b67f09SDavid van Moolenbroek }
268*00b67f09SDavid van Moolenbroek }
269*00b67f09SDavid van Moolenbroek t = p.expect(tp_end_type, "end of test program");
270*00b67f09SDavid van Moolenbroek
271*00b67f09SDavid van Moolenbroek t = p.expect(colon_type, "`:'");
272*00b67f09SDavid van Moolenbroek
273*00b67f09SDavid van Moolenbroek struct timeval s2 = read_timeval(p);
274*00b67f09SDavid van Moolenbroek
275*00b67f09SDavid van Moolenbroek struct timeval s3;
276*00b67f09SDavid van Moolenbroek timersub(&s2, &s1, &s3);
277*00b67f09SDavid van Moolenbroek
278*00b67f09SDavid van Moolenbroek t = p.expect(comma_type, "`,'");
279*00b67f09SDavid van Moolenbroek
280*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "test program name");
281*00b67f09SDavid van Moolenbroek if (t.text() != tpname)
282*00b67f09SDavid van Moolenbroek throw parse_error(t.lineno(), "Test program name used in "
283*00b67f09SDavid van Moolenbroek "terminator does not match "
284*00b67f09SDavid van Moolenbroek "opening");
285*00b67f09SDavid van Moolenbroek
286*00b67f09SDavid van Moolenbroek t = p.expect(nl_type, comma_type,
287*00b67f09SDavid van Moolenbroek "new line or comma_type");
288*00b67f09SDavid van Moolenbroek std::string reason;
289*00b67f09SDavid van Moolenbroek if (t.type() == comma_type) {
290*00b67f09SDavid van Moolenbroek reason = text::trim(p.rest_of_line());
291*00b67f09SDavid van Moolenbroek if (reason.empty())
292*00b67f09SDavid van Moolenbroek throw parse_error(t.lineno(),
293*00b67f09SDavid van Moolenbroek "Empty reason for failed test program");
294*00b67f09SDavid van Moolenbroek t = p.next();
295*00b67f09SDavid van Moolenbroek }
296*00b67f09SDavid van Moolenbroek
297*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_tp_end(&s3, reason));
298*00b67f09SDavid van Moolenbroek }
299*00b67f09SDavid van Moolenbroek
300*00b67f09SDavid van Moolenbroek void
read_tc(void * pptr)301*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::read_tc(void* pptr)
302*00b67f09SDavid van Moolenbroek {
303*00b67f09SDavid van Moolenbroek using atf::parser::parse_error;
304*00b67f09SDavid van Moolenbroek using namespace atf_tps;
305*00b67f09SDavid van Moolenbroek
306*00b67f09SDavid van Moolenbroek atf::parser::parser< tokenizer >& p =
307*00b67f09SDavid van Moolenbroek *reinterpret_cast< atf::parser::parser< tokenizer >* >
308*00b67f09SDavid van Moolenbroek (pptr);
309*00b67f09SDavid van Moolenbroek
310*00b67f09SDavid van Moolenbroek atf::parser::token t = p.expect(tc_start_type, "start of test case");
311*00b67f09SDavid van Moolenbroek
312*00b67f09SDavid van Moolenbroek t = p.expect(colon_type, "`:'");
313*00b67f09SDavid van Moolenbroek
314*00b67f09SDavid van Moolenbroek struct timeval s1 = read_timeval(p);
315*00b67f09SDavid van Moolenbroek
316*00b67f09SDavid van Moolenbroek t = p.expect(comma_type, "`,'");
317*00b67f09SDavid van Moolenbroek
318*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "test case name");
319*00b67f09SDavid van Moolenbroek std::string tcname = t.text();
320*00b67f09SDavid van Moolenbroek
321*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_tc_start(tcname));
322*00b67f09SDavid van Moolenbroek
323*00b67f09SDavid van Moolenbroek t = p.expect(nl_type, "new line");
324*00b67f09SDavid van Moolenbroek
325*00b67f09SDavid van Moolenbroek t = p.expect(tc_end_type, tc_so_type, tc_se_type,
326*00b67f09SDavid van Moolenbroek "end of test case or test case's stdout/stderr line");
327*00b67f09SDavid van Moolenbroek while (t.type() != tc_end_type &&
328*00b67f09SDavid van Moolenbroek (t.type() == tc_so_type || t.type() == tc_se_type)) {
329*00b67f09SDavid van Moolenbroek atf::parser::token t2 = t;
330*00b67f09SDavid van Moolenbroek
331*00b67f09SDavid van Moolenbroek t = p.expect(colon_type, "`:'");
332*00b67f09SDavid van Moolenbroek
333*00b67f09SDavid van Moolenbroek std::string line = p.rest_of_line();
334*00b67f09SDavid van Moolenbroek
335*00b67f09SDavid van Moolenbroek if (t2.type() == tc_so_type) {
336*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_tc_stdout_line(line));
337*00b67f09SDavid van Moolenbroek } else {
338*00b67f09SDavid van Moolenbroek INV(t2.type() == tc_se_type);
339*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_tc_stderr_line(line));
340*00b67f09SDavid van Moolenbroek }
341*00b67f09SDavid van Moolenbroek
342*00b67f09SDavid van Moolenbroek t = p.expect(nl_type, "new line");
343*00b67f09SDavid van Moolenbroek
344*00b67f09SDavid van Moolenbroek t = p.expect(tc_end_type, tc_so_type, tc_se_type,
345*00b67f09SDavid van Moolenbroek "end of test case or test case's stdout/stderr line");
346*00b67f09SDavid van Moolenbroek }
347*00b67f09SDavid van Moolenbroek
348*00b67f09SDavid van Moolenbroek t = p.expect(colon_type, "`:'");
349*00b67f09SDavid van Moolenbroek
350*00b67f09SDavid van Moolenbroek struct timeval s2 = read_timeval(p);
351*00b67f09SDavid van Moolenbroek
352*00b67f09SDavid van Moolenbroek struct timeval s3;
353*00b67f09SDavid van Moolenbroek timersub(&s2, &s1, &s3);
354*00b67f09SDavid van Moolenbroek
355*00b67f09SDavid van Moolenbroek t = p.expect(comma_type, "`,'");
356*00b67f09SDavid van Moolenbroek
357*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "test case name");
358*00b67f09SDavid van Moolenbroek if (t.text() != tcname)
359*00b67f09SDavid van Moolenbroek throw parse_error(t.lineno(),
360*00b67f09SDavid van Moolenbroek "Test case name used in terminator does not "
361*00b67f09SDavid van Moolenbroek "match opening");
362*00b67f09SDavid van Moolenbroek
363*00b67f09SDavid van Moolenbroek t = p.expect(comma_type, "`,'");
364*00b67f09SDavid van Moolenbroek
365*00b67f09SDavid van Moolenbroek t = p.expect(expected_death_type, expected_exit_type, expected_failure_type,
366*00b67f09SDavid van Moolenbroek expected_signal_type, expected_timeout_type, passed_type, failed_type,
367*00b67f09SDavid van Moolenbroek skipped_type, "expected_{death,exit,failure,signal,timeout}, failed, "
368*00b67f09SDavid van Moolenbroek "passed or skipped");
369*00b67f09SDavid van Moolenbroek if (t.type() == passed_type) {
370*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_tc_end("passed", &s3, ""));
371*00b67f09SDavid van Moolenbroek } else {
372*00b67f09SDavid van Moolenbroek std::string state;
373*00b67f09SDavid van Moolenbroek if (t.type() == expected_death_type) state = "expected_death";
374*00b67f09SDavid van Moolenbroek else if (t.type() == expected_exit_type) state = "expected_exit";
375*00b67f09SDavid van Moolenbroek else if (t.type() == expected_failure_type) state = "expected_failure";
376*00b67f09SDavid van Moolenbroek else if (t.type() == expected_signal_type) state = "expected_signal";
377*00b67f09SDavid van Moolenbroek else if (t.type() == expected_timeout_type) state = "expected_timeout";
378*00b67f09SDavid van Moolenbroek else if (t.type() == failed_type) state = "failed";
379*00b67f09SDavid van Moolenbroek else if (t.type() == skipped_type) state = "skipped";
380*00b67f09SDavid van Moolenbroek else UNREACHABLE;
381*00b67f09SDavid van Moolenbroek
382*00b67f09SDavid van Moolenbroek t = p.expect(comma_type, "`,'");
383*00b67f09SDavid van Moolenbroek std::string reason = text::trim(p.rest_of_line());
384*00b67f09SDavid van Moolenbroek if (reason.empty())
385*00b67f09SDavid van Moolenbroek throw parse_error(t.lineno(), "Empty reason for " + state +
386*00b67f09SDavid van Moolenbroek " test case result");
387*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_tc_end(state, &s3, reason));
388*00b67f09SDavid van Moolenbroek }
389*00b67f09SDavid van Moolenbroek
390*00b67f09SDavid van Moolenbroek t = p.expect(nl_type, "new line");
391*00b67f09SDavid van Moolenbroek }
392*00b67f09SDavid van Moolenbroek
393*00b67f09SDavid van Moolenbroek void
read(void)394*00b67f09SDavid van Moolenbroek impl::atf_tps_reader::read(void)
395*00b67f09SDavid van Moolenbroek {
396*00b67f09SDavid van Moolenbroek using atf::parser::parse_error;
397*00b67f09SDavid van Moolenbroek using namespace atf_tps;
398*00b67f09SDavid van Moolenbroek
399*00b67f09SDavid van Moolenbroek std::pair< size_t, atf::parser::headers_map > hml =
400*00b67f09SDavid van Moolenbroek atf::parser::read_headers(m_is, 1);
401*00b67f09SDavid van Moolenbroek atf::parser::validate_content_type(hml.second, "application/X-atf-tps", 3);
402*00b67f09SDavid van Moolenbroek
403*00b67f09SDavid van Moolenbroek tokenizer tkz(m_is, hml.first);
404*00b67f09SDavid van Moolenbroek atf::parser::parser< tokenizer > p(tkz);
405*00b67f09SDavid van Moolenbroek
406*00b67f09SDavid van Moolenbroek try {
407*00b67f09SDavid van Moolenbroek atf::parser::token t;
408*00b67f09SDavid van Moolenbroek
409*00b67f09SDavid van Moolenbroek while ((t = p.expect(tps_count_type, info_type, "tps-count or info "
410*00b67f09SDavid van Moolenbroek "field")).type() == info_type)
411*00b67f09SDavid van Moolenbroek read_info(&p);
412*00b67f09SDavid van Moolenbroek
413*00b67f09SDavid van Moolenbroek t = p.expect(colon_type, "`:'");
414*00b67f09SDavid van Moolenbroek
415*00b67f09SDavid van Moolenbroek t = p.expect(text_type, "number of test programs");
416*00b67f09SDavid van Moolenbroek size_t ntps = string_to_int< std::size_t >(t.text());
417*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_ntps(ntps));
418*00b67f09SDavid van Moolenbroek
419*00b67f09SDavid van Moolenbroek t = p.expect(nl_type, "new line");
420*00b67f09SDavid van Moolenbroek
421*00b67f09SDavid van Moolenbroek size_t i = 0;
422*00b67f09SDavid van Moolenbroek while (p.good() && i < ntps) {
423*00b67f09SDavid van Moolenbroek try {
424*00b67f09SDavid van Moolenbroek read_tp(&p);
425*00b67f09SDavid van Moolenbroek i++;
426*00b67f09SDavid van Moolenbroek } catch (const parse_error& pe) {
427*00b67f09SDavid van Moolenbroek p.add_error(pe);
428*00b67f09SDavid van Moolenbroek p.reset(nl_type);
429*00b67f09SDavid van Moolenbroek }
430*00b67f09SDavid van Moolenbroek }
431*00b67f09SDavid van Moolenbroek
432*00b67f09SDavid van Moolenbroek while ((t = p.expect(eof_type, info_type, "end of stream or info "
433*00b67f09SDavid van Moolenbroek "field")).type() == info_type)
434*00b67f09SDavid van Moolenbroek read_info(&p);
435*00b67f09SDavid van Moolenbroek ATF_PARSER_CALLBACK(p, got_eof());
436*00b67f09SDavid van Moolenbroek } catch (const parse_error& pe) {
437*00b67f09SDavid van Moolenbroek p.add_error(pe);
438*00b67f09SDavid van Moolenbroek p.reset(nl_type);
439*00b67f09SDavid van Moolenbroek }
440*00b67f09SDavid van Moolenbroek }
441