libzypp 17.28.8
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 if ( _pimpl->properties.find( name) == _pimpl->properties.end() )
81 return def;
82 return _pimpl->properties.at( name );
83 }
84
85 const std::map<std::string, std::string> &TestcaseTrial::Node::properties() const
86 { return _pimpl->properties; }
87
88 std::map<std::string, std::string> &TestcaseTrial::Node::properties()
89 { return _pimpl->properties; }
90
91 const std::vector<std::shared_ptr<TestcaseTrial::Node> > &TestcaseTrial::Node::children() const
92 { return _pimpl->children; }
93
94 std::vector<std::shared_ptr<TestcaseTrial::Node> > &TestcaseTrial::Node::children()
95 { return _pimpl->children; }
96
97 bool LoadTestcase::Impl::loadHelix(const zypp::filesystem::Pathname &filename, std::string *err)
98 {
99 xmlDocPtr xml_doc = xmlParseFile ( filename.c_str() );
100 if (xml_doc == NULL) {
101 if ( err ) *err = (str::Str() << "Can't parse test file '" << filename << "'");
102 return false;
103 }
104
105
106 auto root = helix::detail::XmlNode (xmlDocGetRootElement (xml_doc));
107
108 DBG << "Parsing file '" << filename << "'" << std::endl;
109
110 if (!root.equals("test")) {
111 if ( err ) *err = (str::Str() << "Node not 'test' in parse_xml_test():" << root.name() << "'");
112 return false;
113 }
114
115 bool setupDone = false;
116 auto node = root.children();
117 while (node) {
118 if (node->type() == XML_ELEMENT_NODE) {
119 if (node->equals( "setup" )) {
120 if ( setupDone ) {
121 if ( err ) *err = "Multiple setup tags found, this is not supported";
122 return false;
123 }
124 setupDone = true;
125 if ( !helix::detail::parseSetup( *node, _setup, err ) )
126 return false;
127
128 } else if (node->equals( "trial" )) {
129 if ( !setupDone ) {
130 if ( err ) *err = "Any trials must be preceeded by the setup!";
131 return false;
132 }
133 TestcaseTrial trial;
134 if ( !helix::detail::parseTrial( *node, trial, err ) )
135 return false;
136 _trials.push_back( trial );
137 } else {
138 ERR << "Unknown tag '" << node->name() << "' in test" << std::endl;
139 }
140 }
141 node = ( node->next() );
142 }
143 xmlFreeDoc (xml_doc);
144 return true;
145 }
146
148 {
149 DBG << "Parsing file '" << path << "'" << std::endl;
150
151 const auto makeError = [&]( const std::string_view &errStr ){
152 if ( err ) *err = errStr;
153 return false;
154 };
155
156 YAML::Node control;
157 try {
158 control = YAML::LoadFile( path.asString() );
159
160 if ( control.Type() != YAML::NodeType::Map )
161 return makeError("Root node must be of type Map.");
162
163 const auto &setup = control["setup"];
164 if ( !setup )
165 return makeError("The 'setup' section is required.");
166
167 if ( !yamltest::detail::parseSetup( setup, _setup, err) )
168 return false;
169
170 const auto &trials = control["trials"];
171 if ( !trials )
172 return makeError("The 'trials' section is required.");
173 if ( trials.Type() != YAML::NodeType::Sequence )
174 return makeError("The 'trials' section must be of type Sequence.");
175
176 for ( const auto &trial : trials ) {
178 if ( !trial["trial"] )
179 return makeError("Every element in the trials sequence needs to have the 'trial' key.");
180
181 if ( !yamltest::detail::parseTrial( trial["trial"], t, err) )
182 return false;
183 _trials.push_back( t );
184 }
185 } catch ( YAML::Exception &e ) {
186 if ( err ) *err = e.what();
187 return false;
188 } catch ( ... ) {
189 if ( err ) *err = "Unknown error when parsing the control file";
190 return false;
191 }
192 return true;
193 }
194
196 { }
197
199 { }
200
202 {
203 const auto t = testcaseTypeAt( path );
204 if ( t == LoadTestcase::None ) {
205 if ( err ) *err = "Unsopported or no testcase in directory";
206 return false;
207 }
208
209 // reset everything
210 _pimpl.reset( new Impl() );
211 _pimpl->_setup.data().globalPath = path;
212
213 switch (t) {
215 return _pimpl->loadHelix( path / helixControlFile, err );
217 return _pimpl->loadYaml( path / yamlControlFile, err );
218 default:
219 return false;
220 }
221 }
222
224 {
225 if ( filesystem::PathInfo( path / helixControlFile ).isFile() ) {
226 return LoadTestcase::Helix;
227 } else if ( filesystem::PathInfo( path / yamlControlFile ).isFile() ) {
228 return LoadTestcase::Yaml;
229 }
230 return LoadTestcase::None;
231 }
232
234 {
235 return _pimpl->_setup;
236 }
237
239 {
240 return _pimpl->_trials;
241 }
242
243}
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
std::ostream & node(std::ostream &out_r, const std::string &name_r, Node::Attr attr_r)
Definition: Xml.h:203
bool loadHelix(const Pathname &filename, std::string *err)
Definition: LoadTestcase.cc:97
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:91
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:85
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:54
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