libzypp 17.31.23
LoadTestcase.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include "LoadTestcase.h"
13#include "HelixHelpers.h"
14#include "YamlTestcaseHelpers.h"
15#include <zypp/PathInfo.h>
16#include <zypp/base/LogControl.h>
17
19
20 static const std::string helixControlFile = "solver-test.xml";
21 static const std::string yamlControlFile = "zypp-control.yaml";
22
26
27 bool loadHelix (const Pathname &filename, std::string *err);
28
29 bool loadYaml ( const Pathname &path, std::string *err);
30 };
31
32
34 {
35 std::vector<Node> nodes;
36 Impl *clone() const { return new Impl(*this); }
37 };
38
40 {
41 std::string name;
42 std::string value;
43 std::map<std::string, std::string> properties;
44 std::vector<std::shared_ptr<Node>> children;
45 Impl *clone() const { return new Impl(*this); }
46 };
47
49 { }
50
52 { }
53
54 const std::vector<TestcaseTrial::Node> &TestcaseTrial::nodes() const
55 { return _pimpl->nodes; }
56
57 std::vector<TestcaseTrial::Node> &TestcaseTrial::nodes()
58 { return _pimpl->nodes; }
59
60 TestcaseTrial::Node::Node() : _pimpl ( new Impl() )
61 { }
62
64 { }
65
66 const std::string &TestcaseTrial::Node::name() const
67 { return _pimpl->name; }
68
70 { return _pimpl->name; }
71
72 const std::string &TestcaseTrial::Node::value() const
73 { return _pimpl->value; }
74
76 { return _pimpl->value; }
77
78 const std::string &TestcaseTrial::Node::getProp( const std::string &name, const std::string &def ) const
79 {
80 auto it { _pimpl->properties.find( name ) };
81 return it == _pimpl->properties.end() ? def : it->second;
82 }
83
84 const std::map<std::string, std::string> &TestcaseTrial::Node::properties() const
85 { return _pimpl->properties; }
86
87 std::map<std::string, std::string> &TestcaseTrial::Node::properties()
88 { return _pimpl->properties; }
89
90 const std::vector<std::shared_ptr<TestcaseTrial::Node> > &TestcaseTrial::Node::children() const
91 { return _pimpl->children; }
92
93 std::vector<std::shared_ptr<TestcaseTrial::Node> > &TestcaseTrial::Node::children()
94 { return _pimpl->children; }
95
96 bool LoadTestcase::Impl::loadHelix(const zypp::filesystem::Pathname &filename, std::string *err)
97 {
98 xmlDocPtr xml_doc = xmlParseFile ( filename.c_str() );
99 if (xml_doc == NULL) {
100 if ( err ) *err = (str::Str() << "Can't parse test file '" << filename << "'");
101 return false;
102 }
103
104
105 auto root = helix::detail::XmlNode (xmlDocGetRootElement (xml_doc));
106
107 DBG << "Parsing file '" << filename << "'" << std::endl;
108
109 if (!root.equals("test")) {
110 if ( err ) *err = (str::Str() << "Node not 'test' in parse_xml_test():" << root.name() << "'");
111 return false;
112 }
113
114 bool setupDone = false;
115 auto node = root.children();
116 while (node) {
117 if (node->type() == XML_ELEMENT_NODE) {
118 if (node->equals( "setup" )) {
119 if ( setupDone ) {
120 if ( err ) *err = "Multiple setup tags found, this is not supported";
121 return false;
122 }
123 setupDone = true;
124 if ( !helix::detail::parseSetup( *node, _setup, err ) )
125 return false;
126
127 } else if (node->equals( "trial" )) {
128 if ( !setupDone ) {
129 if ( err ) *err = "Any trials must be preceded by the setup!";
130 return false;
131 }
132 TestcaseTrial trial;
133 if ( !helix::detail::parseTrial( *node, trial, err ) )
134 return false;
135 _trials.push_back( trial );
136 } else {
137 ERR << "Unknown tag '" << node->name() << "' in test" << std::endl;
138 }
139 }
140 node = ( node->next() );
141 }
142 xmlFreeDoc (xml_doc);
143 return true;
144 }
145
147 {
148 DBG << "Parsing file '" << path << "'" << std::endl;
149
150 const auto makeError = [&]( const std::string_view &errStr ){
151 if ( err ) *err = errStr;
152 return false;
153 };
154
155 YAML::Node control;
156 try {
157 control = YAML::LoadFile( path.asString() );
158
159 if ( control.Type() != YAML::NodeType::Map )
160 return makeError("Root node must be of type Map.");
161
162 const auto &setup = control["setup"];
163 if ( !setup )
164 return makeError("The 'setup' section is required.");
165
166 if ( !yamltest::detail::parseSetup( setup, _setup, err) )
167 return false;
168
169 const auto &trials = control["trials"];
170 if ( !trials )
171 return makeError("The 'trials' section is required.");
172 if ( trials.Type() != YAML::NodeType::Sequence )
173 return makeError("The 'trials' section must be of type Sequence.");
174
175 for ( const auto &trial : trials ) {
177 if ( !trial["trial"] )
178 return makeError("Every element in the trials sequence needs to have the 'trial' key.");
179
180 if ( !yamltest::detail::parseTrial( trial["trial"], t, err) )
181 return false;
182 _trials.push_back( t );
183 }
184 } catch ( YAML::Exception &e ) {
185 if ( err ) *err = e.what();
186 return false;
187 } catch ( ... ) {
188 if ( err ) *err = "Unknown error when parsing the control file";
189 return false;
190 }
191 return true;
192 }
193
195 { }
196
198 { }
199
201 {
202 const auto t = testcaseTypeAt( path );
203 if ( t == LoadTestcase::None ) {
204 if ( err ) *err = "Unsopported or no testcase in directory";
205 return false;
206 }
207
208 // reset everything
209 _pimpl.reset( new Impl() );
210 _pimpl->_setup.data().globalPath = path;
211
212 switch (t) {
214 return _pimpl->loadHelix( path / helixControlFile, err );
216 return _pimpl->loadYaml( path / yamlControlFile, err );
217 default:
218 return false;
219 }
220 }
221
223 {
224 if ( filesystem::PathInfo( path / helixControlFile ).isFile() ) {
225 return LoadTestcase::Helix;
226 } else if ( filesystem::PathInfo( path / yamlControlFile ).isFile() ) {
227 return LoadTestcase::Yaml;
228 }
229 return LoadTestcase::None;
230 }
231
233 {
234 return _pimpl->_setup;
235 }
236
238 {
239 return _pimpl->_trials;
240 }
241
242}
Wrapper class for stat/lstat.
Definition: PathInfo.h:221
const char * c_str() const
String representation.
Definition: Pathname.h:110
const std::string & asString() const
String representation.
Definition: Pathname.h:91
const TestcaseSetup & setupInfo() const
const TestcaseTrials & trialInfo() const
std::unique_ptr< Impl > _pimpl
Definition: LoadTestcase.h:80
static Type testcaseTypeAt(const zypp::Pathname &path)
bool loadTestcaseAt(const zypp::Pathname &path, std::string *err)
std::vector< TestcaseTrial > TestcaseTrials
Definition: LoadTestcase.h:62
bool parseTrial(const XmlNode &trial, zypp::misc::testcase::TestcaseTrial &target, std::string *)
Definition: HelixHelpers.h:303
bool parseSetup(const XmlNode &setup, zypp::misc::testcase::TestcaseSetup &t, std::string *err)
Definition: HelixHelpers.h:138
bool parseSetup(const YAML::Node &setup, zypp::misc::testcase::TestcaseSetup &t, std::string *err)
bool parseTrial(const YAML::Node &trial, zypp::misc::testcase::TestcaseTrial &target, std::string *err)
static const std::string yamlControlFile
Definition: LoadTestcase.cc:21
static const std::string helixControlFile
Definition: LoadTestcase.cc:20
bool loadHelix(const Pathname &filename, std::string *err)
Definition: LoadTestcase.cc:96
bool loadYaml(const Pathname &path, std::string *err)
std::map< std::string, std::string > properties
Definition: LoadTestcase.cc:43
std::vector< std::shared_ptr< Node > > children
Definition: LoadTestcase.cc:44
const std::vector< std::shared_ptr< Node > > & children() const
Definition: LoadTestcase.cc:90
const std::string & name() const
Definition: LoadTestcase.cc:66
const std::string & getProp(const std::string &name, const std::string &def=std::string()) const
Definition: LoadTestcase.cc:78
const std::map< std::string, std::string > & properties() const
Definition: LoadTestcase.cc:84
const std::string & value() const
Definition: LoadTestcase.cc:72
const std::vector< Node > & nodes() const
Definition: LoadTestcase.cc:54
RWCOW_pointer< Impl > _pimpl
Definition: LoadTestcase.h:55
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:212
#define DBG
Definition: Logger.h:95
#define ERR
Definition: Logger.h:98