12#ifndef ZYPP_MISC_YAMLTESTCASEHELPERS_H
13#define ZYPP_MISC_YAMLTESTCASEHELPERS_H
15#include <zypp/base/LogControl.h>
19#include <yaml-cpp/yaml.h>
27 auto &target = t.
data();
28 MIL <<
"Parsing setup node " << std::endl;
29 for ( YAML::const_iterator it = setup.begin(); it != setup.end(); it++ ) {
31 const std::string &key = it->first.as<std::string>();
32 const auto &data = it->second;
34 MIL <<
"Found key " << key << std::endl;
37 auto readListInlineOrFromFile = [&](
const auto &cb , std::string *err ) ->
bool {
38 if ( data.Type() == YAML::NodeType::Sequence ) {
40 for (
const auto &node: data ) {
41 if ( !cb( node, err ) )
return false;
44 MIL <<
"Loaded " << cnt <<
" Elements inline" << std::endl;
46 const std::string &fName = data.as<std::string>();
47 MIL <<
"Trying to load list from file " << fName << std::endl;
49 auto doc = YAML::LoadFile( fName );
50 if ( doc.Type() != YAML::NodeType::Sequence ) {
51 if ( err ) *err =
"Expected the top node to be a sequence in external file for key: ";
56 for (
const auto &node : doc ) {
57 if ( !cb( node, err ) )
return false;
60 MIL <<
"Loaded " << cnt <<
" Elements from file" << std::endl;
61 }
catch ( YAML::Exception &e ) {
65 if ( !e.mark.is_null() ) {
66 errStr <<
" Line: " << e.mark.line <<
" Col: " << e.mark.column <<
" pos: " << e.mark.pos;
72 if ( err ) *err =
zypp::str::Str() <<
"Unknown error when parsing the file for " << key;
79 if ( key ==
"resolverFlags" ) {
80#define if_SolverFlag( N ) if ( data[#N] ) { target.N = data[#N].as<bool>(); }
81 if_SolverFlag( ignorealreadyrecommended )
if ( data[
"ignorealready"] ) { target.ignorealreadyrecommended = data[
"ignorealready"].as<
bool>(); }
82 if_SolverFlag( onlyRequires )
if ( data[
"ignorerecommended"] ) { target.onlyRequires = data[
"ignorerecommended"].as<
bool>(); }
97 if ( data[
"focus"] ) {
98 target.resolverFocus = zypp::resolverFocusFromString( data[
"focus"].as<std::string>() );
100 }
else if ( key == (
"system") ) {
105 data[
"file"].as<std::string>()
108 else if ( key == (
"hardwareInfo") ) {
109 target.hardwareInfoFile = data.as<std::string>();
111 else if ( key == (
"modalias") ) {
112 bool success = readListInlineOrFromFile( [&target](
const YAML::Node &dataNode,
auto ){
113 target.modaliasList.push_back( dataNode.as<std::string>() );
116 if ( !success )
return false;
118 else if ( key == (
"multiversion") ) {
119 bool success = readListInlineOrFromFile( [&target](
const YAML::Node &dataNode,
auto ){
120 target.multiversionSpec.insert( dataNode.as<std::string>() );
123 if ( !success )
return false;
125 else if (key == (
"channels")) {
126 bool success = readListInlineOrFromFile( [&target](
const YAML::Node &dataNode,
auto ){
127 std::string name = dataNode[
"alias"].as<std::string>();
128 std::string file = dataNode[
"file"].as<std::string>();
131 if ( dataNode[
"priority"] )
132 prio = dataNode[
"priority"].as<
unsigned>();
142 if ( !success )
return false;
144 else if ( key == (
"sources") )
146 bool success = readListInlineOrFromFile( [&target](
const YAML::Node &dataNode,
auto ){
147 std::string url = dataNode[
"url"].as<std::string>();
148 std::string alias = dataNode[
"name"].as<std::string>();
157 if ( !success )
return false;
159 else if ( key == (
"force-install") )
161 bool success = readListInlineOrFromFile( [&target](
const YAML::Node &dataNode,
auto ){
163 dataNode[
"channel"].as<std::string>(),
164 dataNode[
"package"].as<std::string>(),
165 dataNode[
"kind"].as<std::string>()
169 if ( !success )
return false;
171 else if ( key == (
"mediaid") )
173 target.show_mediaid = data.as<
bool>();
175 else if ( key == (
"arch") ) {
176 std::string architecture = data.as<std::string>();
177 if ( architecture.empty() ) {
178 if (err) *err =
zypp::str::Str() <<
"Property 'arch' in setup can not be empty." << std::endl;
182 MIL <<
"Setting architecture to '" << architecture <<
"'" << std::endl;
183 target.architecture =
zypp::Arch( architecture );
186 else if ( key == (
"locales") )
188 bool success = readListInlineOrFromFile( [&target](
const YAML::Node &dataNode, std::string *err ){
190 std::string fate = dataNode[
"fate"].as<std::string>();
192 if (err) *err =
zypp::str::Str() <<
"Bad or missing name in locale..." << std::endl;
195 else if ( fate ==
"added" ) {
196 target.localesTracker.added().insert( loc );
198 else if ( fate ==
"removed" ) {
199 target.localesTracker.removed().insert( loc );
202 target.localesTracker.current().insert( loc );
206 if ( !success )
return false;
208 else if ( key == (
"vendors") )
210 bool success = readListInlineOrFromFile( [&target](
const YAML::Node & dataNode, std::string * err ) {
211 std::vector<std::string> vlist;
212 for (
const auto & node : dataNode )
213 vlist.push_back( node.as<std::string>() );
214 if ( ! vlist.empty() )
215 target.vendorLists.push_back( std::move(vlist) );
218 if ( !success )
return false;
220 else if ( key == (
"autoinst") ) {
221 bool success = readListInlineOrFromFile( [&](
const YAML::Node &dataNode,
auto ){
222 target.autoinstalled.push(
zypp::IdString( dataNode.as<std::string>() ).
id() );
225 if ( !success )
return false;
227 else if ( key == (
"systemCheck") ) {
228 target.systemCheck = data.as<std::string>();
230 else if ( key == (
"setlicencebit") ) {
231 target.set_licence = data.as<
bool>();
234 ERR <<
"Ignoring unrecognized tag '" << key <<
"' in setup" << std::endl;
240 template <
typename T>
241 bool parseJobs (
const YAML::Node &trial, std::vector<T> &target, std::string *err );
243 template <
typename T>
244 bool parseSingleJob (
const YAML::Node &jobNode, std::vector<T> &target, std::string *err ) {
246 constexpr bool isSubNode = std::is_same_v<T, std::shared_ptr<zypp::misc::testcase::TestcaseTrial::Node>>;
247 if ( jobNode[
"include"] ) {
249 const auto &fName = jobNode[
"include"].as<std::string>();
250 MIL <<
"Including file " << fName << std::endl;
252 auto doc = YAML::LoadFile( fName );
255 MIL <<
"Including file " << fName <<
"was successful" << std::endl;
256 }
catch ( YAML::Exception &e ) {
257 if ( err ) *err = e.what();
260 if ( err ) *err =
zypp::str::Str() <<
"Unknown error when parsing the file: " << fName;
267 if ( !jobNode[
"job"] ) {
270 const auto &mark = jobNode.Mark();
271 errStr <<
"'job' key missing from trial node.";
272 if ( !mark.is_null() ) {
273 errStr <<
" Line: " << mark.line <<
" Col: " << mark.column <<
" pos: " << mark.pos;
280 for (
const auto &elem : jobNode ) {
281 const std::string &key = elem.first.as<std::string>();
282 const auto &data = elem.second;
283 if ( key ==
"job" ) {
284 n.
name() = data.as<std::string>();
285 }
else if ( key ==
"__content") {
286 n.
value() = data.as<std::string>();
288 if( data.IsScalar() ) {
289 n.
properties().insert( { key, data.as<std::string>() } );
290 }
else if ( data.IsSequence() ) {
296 }
else if ( data.IsMap() ) {
303 ERR <<
"Ignoring field " << key <<
" with unsupported type:" << data.Type() << std::endl;
307 if constexpr ( isSubNode ) {
308 target.push_back( std::make_shared<zypp::misc::testcase::TestcaseTrial::Node>( std::move(n) ) );
310 target.push_back( std::move(n) );
315 template <
typename T>
316 bool parseJobs (
const YAML::Node &trial, std::vector<T> &target, std::string *err ) {
317 for (
const auto &jobNode : trial ) {
325 MIL <<
"Parsing trials." << std::endl;
Access to the sat-pools string space.
IdType id() const
Expert backdoor.
'Language[_Country]' codes.
TestcaseSetupImpl & data()
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)
bool parseJobs(const YAML::Node &trial, std::vector< T > &target, std::string *err)
bool parseSingleJob(const YAML::Node &jobNode, std::vector< T > &target, std::string *err)
const std::vector< std::shared_ptr< Node > > & children() const
const std::string & name() const
const std::map< std::string, std::string > & properties() const
const std::string & value() const
const std::vector< Node > & nodes() const
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...