1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/solver/detail/Testcase.cc
17 #include "zypp/solver/detail/Testcase.h"
18 #include "zypp/base/Logger.h"
19 #include "zypp/base/LogControl.h"
20 #include "zypp/ZConfig.h"
21 #include "zypp/PathInfo.h"
22 #include "zypp/Product.h"
23 #include "zypp/Package.h"
24 #include "zypp/Edition.h"
25 #include "zypp/parser/xml_escape_parser.hpp"
26 #include "zypp/base/String.h"
27 #include "zypp/base/PtrTypes.h"
28 #include "zypp/Capabilities.h"
29 #include "zypp/sat/Solvable.h"
32 /////////////////////////////////////////////////////////////////////////
34 { ///////////////////////////////////////////////////////////////////////
35 ///////////////////////////////////////////////////////////////////////
37 { /////////////////////////////////////////////////////////////////////
38 /////////////////////////////////////////////////////////////////////
40 { ///////////////////////////////////////////////////////////////////
46 using namespace zypp::str;
48 IMPL_PTR_TYPE(HelixResolvable);
50 static std::string xml_escape( const std::string &text )
52 iobind::parser::xml_escape_parser parser;
53 return parser.escape(text);
56 static std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false )
59 result += "<" + tag + ">";
62 result += xml_escape(text);
66 result += "</" + tag + ">";
72 std::string helixXML( const T &obj ); //undefined
75 std::string helixXML( const Edition &edition )
78 str << xml_tag_enclose(edition.version(), "version");
79 if (!edition.release().empty())
80 str << xml_tag_enclose(edition.release(), "release");
81 if (edition.epoch() != Edition::noepoch)
82 str << xml_tag_enclose(numstring(edition.epoch()), "epoch");
87 std::string helixXML( const Arch &arch )
90 str << xml_tag_enclose(arch.asString(), "arch");
95 std::string helixXML( const Capability &cap )
98 str << "<dep name='" << xml_escape(cap.asString()) << "' />" << endl;
104 std::string helixXML( const Capabilities &caps )
107 Capabilities::const_iterator it = caps.begin();
109 for ( ; it != caps.end(); ++it)
111 str << TAB2 << helixXML((*it));
118 std::string helixXML( const CapabilitySet &caps )
121 CapabilitySet::const_iterator it = caps.begin();
123 for ( ; it != caps.end(); ++it)
125 str << TAB2 << helixXML((*it));
133 std::string helixXML( const Dependencies &dep )
136 if ( dep[Dep::PROVIDES].size() > 0 )
137 str << TAB << xml_tag_enclose(helixXML(dep[Dep::PROVIDES]), "provides") << endl;
138 if ( dep[Dep::CONFLICTS].size() > 0 )
139 str << TAB << xml_tag_enclose(helixXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
140 if ( dep[Dep::OBSOLETES].size() > 0 )
141 str << TAB << xml_tag_enclose(helixXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
142 if ( dep[Dep::FRESHENS].size() > 0 )
143 str << TAB << xml_tag_enclose(helixXML(dep[Dep::FRESHENS]), "freshens") << endl;
144 if ( dep[Dep::REQUIRES].size() > 0 )
145 str << TAB << xml_tag_enclose(helixXML(dep[Dep::REQUIRES]), "requires") << endl;
146 if ( dep[Dep::RECOMMENDS].size() > 0 )
147 str << TAB << xml_tag_enclose(helixXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
148 if ( dep[Dep::ENHANCES].size() > 0 )
149 str << TAB << xml_tag_enclose(helixXML(dep[Dep::ENHANCES]), "enhances") << endl;
150 if ( dep[Dep::SUPPLEMENTS].size() > 0 )
151 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
152 if ( dep[Dep::SUGGESTS].size() > 0 )
153 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUGGESTS]), "suggests") << endl;
157 inline string helixXML( const Resolvable::constPtr &obj, Dep deptag_r )
160 Capabilities caps( obj->dep(deptag_r) );
161 if ( ! caps.empty() )
162 out << TAB << xml_tag_enclose(helixXML(caps), deptag_r.asString()) << endl;
166 std::string helixXML( const PoolItem &item )
168 const Resolvable::constPtr resolvable = item.resolvable();
170 str << "<" << toLower (resolvable->kind().asString()) << ">" << endl;
171 str << TAB << xml_tag_enclose (resolvable->name(), "name", true) << endl;
172 str << TAB << xml_tag_enclose (item->vendor(), "vendor", true) << endl;
173 if ( isKind<Package>(resolvable) ) {
174 str << TAB << "<history>" << endl << TAB << "<update>" << endl;
175 str << TAB2 << helixXML (resolvable->arch()) << endl;
176 str << TAB2 << helixXML (resolvable->edition()) << endl;
177 str << TAB << "</update>" << endl << TAB << "</history>" << endl;
179 str << TAB << helixXML (resolvable->arch()) << endl;
180 str << TAB << helixXML (resolvable->edition()) << endl;
182 str << helixXML( resolvable, Dep::PROVIDES);
183 str << helixXML( resolvable, Dep::PREREQUIRES);
184 str << helixXML( resolvable, Dep::CONFLICTS);
185 str << helixXML( resolvable, Dep::OBSOLETES);
186 str << helixXML( resolvable, Dep::FRESHENS);
187 str << helixXML( resolvable, Dep::REQUIRES);
188 str << helixXML( resolvable, Dep::RECOMMENDS);
189 str << helixXML( resolvable, Dep::ENHANCES);
190 str << helixXML( resolvable, Dep::SUPPLEMENTS);
191 str << helixXML( resolvable, Dep::SUGGESTS);
193 str << "</" << toLower (resolvable->kind().asString()) << ">" << endl;
197 //---------------------------------------------------------------------------
200 :dumpPath("/var/log/YaST2/solverTestcase")
204 Testcase::Testcase(const std::string & path)
210 Testcase::~Testcase()
215 bool Testcase::createTestcasePool(const ResPool &pool)
217 PathInfo path (dumpPath);
219 if ( !path.isExist() ) {
220 if (zypp::filesystem::mkdir (dumpPath)!=0) {
221 ERR << "Cannot create directory " << dumpPath << endl;
226 ERR << dumpPath << " is not a directory." << endl;
230 zypp::filesystem::clean_dir (dumpPath);
233 RepositoryTable repoTable;
234 HelixResolvable system (dumpPath + "/solver-system.xml.gz");
236 for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
238 if ( it->status().isInstalled() ) {
240 system.addResolvable (*it);
243 sat::Repo repo = it->resolvable()->satSolvable().repo();
244 if (repoTable.find (repo) == repoTable.end()) {
245 repoTable[repo] = new HelixResolvable(dumpPath + "/"
246 + str::numstring((long)repo.id())
247 + "-package.xml.gz");
249 repoTable[repo]->addResolvable (*it);
255 bool Testcase::createTestcase(Resolver & resolver, bool dumpPool, bool runSolver)
257 PathInfo path (dumpPath);
259 if ( !path.isExist() ) {
260 if (zypp::filesystem::mkdir (dumpPath)!=0) {
261 ERR << "Cannot create directory " << dumpPath << endl;
266 ERR << dumpPath << " is not a directory." << endl;
269 // remove old stuff if pool will be dump
271 zypp::filesystem::clean_dir (dumpPath);
275 zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" );
276 zypp::base::LogControl::TmpExcessive excessive;
278 resolver.reset(true); // true = resetting all valid solverresults
279 resolver.resolvePool();
281 zypp::base::LogControl::instance().logfile( "/var/log/YaST2/y2log" );
284 ResPool pool = resolver.pool();
285 RepositoryTable repoTable;
286 PoolItemList items_to_install;
287 PoolItemList items_to_remove;
288 PoolItemList items_locked;
289 PoolItemList items_keep;
290 PoolItemList language;
291 HelixResolvable_Ptr system = NULL;
294 system = new HelixResolvable(dumpPath + "/solver-system.xml.gz");
296 for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
298 Resolvable::constPtr res = it->resolvable();
300 #warning NO MORE LANGUAGE RESOLVABLE
301 // - use pools list of requested locales and pass it as 'LocaleList language'
302 // - restore the list via Pool::setRequestedLocales.
304 if (isKind<Language>(res)) {
305 if ( it->status().isInstalled()
306 || it->status().isToBeInstalled()) {
307 language.push_back (*it);
311 if ( system && it->status().isInstalled() ) {
313 system->addResolvable (*it);
316 sat::Repo repo = it->resolvable()->satSolvable().repo();
318 if (repoTable.find (repo) == repoTable.end()) {
319 repoTable[repo] = new HelixResolvable(dumpPath + "/"
320 + str::numstring((long)repo.id())
321 + "-package.xml.gz");
323 repoTable[repo]->addResolvable (*it);
327 if ( it->status().isToBeInstalled()
328 && !(it->status().isBySolver())) {
329 items_to_install.push_back (*it);
331 if ( it->status().isKept()
332 && !(it->status().isBySolver())) {
333 items_keep.push_back (*it);
335 if ( it->status().isToBeUninstalled()
336 && !(it->status().isBySolver())) {
337 items_to_remove.push_back (*it);
339 if ( it->status().isLocked()
340 && !(it->status().isBySolver())) {
341 items_locked.push_back (*it);
345 // writing control file "*-test.xml"
347 HelixControl control (dumpPath + "/solver-test.xml.gz",
349 ZConfig::instance().systemArchitecture(),
352 for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) {
353 control.installResolvable (iter->resolvable(), iter->status());
356 for (PoolItemList::const_iterator iter = items_locked.begin(); iter != items_locked.end(); iter++) {
357 control.lockResolvable (iter->resolvable(), iter->status());
360 for (PoolItemList::const_iterator iter = items_keep.begin(); iter != items_keep.end(); iter++) {
361 control.keepResolvable (iter->resolvable(), iter->status());
364 for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) {
365 control.deleteResolvable (iter->resolvable(), iter->status());
368 control.addDependencies (resolver.extraRequires(), resolver.extraConflicts());
373 //---------------------------------------------------------------------------
375 HelixResolvable::HelixResolvable(const std::string & path)
378 file = new ofgzstream(path.c_str());
380 ZYPP_THROW (Exception( "Can't open " + path ) );
383 *file << "<channel><subchannel>" << endl;
386 HelixResolvable::~HelixResolvable()
388 *file << "</subchannel></channel>" << endl;
393 void HelixResolvable::addResolvable(const PoolItem item)
395 *file << helixXML (item);
398 //---------------------------------------------------------------------------
400 HelixControl::HelixControl(const std::string & controlPath,
401 const RepositoryTable & repoTable,
402 const Arch & systemArchitecture,
403 const PoolItemList &languages,
404 const std::string & systemPath)
405 :dumpFile (controlPath)
407 file = new ofgzstream(controlPath.c_str());
409 ZYPP_THROW (Exception( "Can't open " + controlPath ) );
412 *file << "<?xml version=\"1.0\"?>" << endl
413 << "<!-- testcase generated by YaST -->" << endl
415 << "<setup arch=\"" << systemArchitecture << "\">" << endl
416 << TAB << "<system file=\"" << systemPath << "\"/>" << endl << endl;
417 for ( RepositoryTable::const_iterator it = repoTable.begin();
418 it != repoTable.end(); ++it ) {
419 RepoInfo repo = it->first.info();
420 *file << TAB << "<!-- " << endl
421 << TAB << "- alias : " << repo.alias() << endl;
422 for ( RepoInfo::urls_const_iterator itUrl = repo.baseUrlsBegin();
423 itUrl != repo.baseUrlsEnd();
426 *file << TAB << "- url : " << *itUrl << endl;
428 *file << TAB << "- path : " << repo.path() << endl;
429 *file << TAB << "- type : " << repo.type() << endl;
430 *file << TAB << " -->" << endl;
432 *file << TAB << "<channel file=\"" << str::numstring((long)it->first.id())
433 << "-package.xml\" name=\"" << repo.alias()
434 << "\" />" << endl << endl;
436 for (PoolItemList::const_iterator iter = languages.begin(); iter != languages.end(); iter++) {
437 *file << TAB << "<locale name=\"" << iter->resolvable()->name()
440 *file << "</setup>" << endl
442 << "<showpool all=\"yes\"/>" << endl;
445 HelixControl::HelixControl()
446 :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
448 HelixControl (dumpFile);
451 HelixControl::~HelixControl()
453 *file << "</trial>" << endl
454 << "</test>" << endl;
458 void HelixControl::installResolvable(const ResObject::constPtr &resObject,
459 const ResStatus &status)
461 *file << "<install channel=\"" << resObject->repoInfo().alias() << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
462 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
463 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
464 << " status=\"" << status << "\""
468 void HelixControl::lockResolvable(const ResObject::constPtr &resObject,
469 const ResStatus &status)
471 *file << "<lock channel=\"" << resObject->repoInfo().alias() << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
472 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
473 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
474 << " status=\"" << status << "\""
478 void HelixControl::keepResolvable(const ResObject::constPtr &resObject,
479 const ResStatus &status)
481 *file << "<keep channel=\"" << resObject->repoInfo().alias() << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
482 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
483 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
484 << " status=\"" << status << "\""
488 void HelixControl::deleteResolvable(const ResObject::constPtr &resObject,
489 const ResStatus &status)
491 *file << "<uninstall " << " kind=\"" << toLower (resObject->kind().asString()) << "\""
492 << " name=\"" << resObject->name() << "\""
493 << " status=\"" << status << "\""
497 void HelixControl::addDependencies (const CapabilitySet & capRequire, const CapabilitySet & capConflict)
499 for (CapabilitySet::const_iterator iter = capRequire.begin(); iter != capRequire.end(); iter++) {
500 *file << "<addRequire " << " name=\"" << iter->asString() << "\"" << "/>" << endl;
502 for (CapabilitySet::const_iterator iter = capConflict.begin(); iter != capConflict.end(); iter++) {
503 *file << "<addConflict " << " name=\"" << iter->asString() << "\"" << "/>" << endl;
508 ///////////////////////////////////////////////////////////////////
509 };// namespace detail
510 /////////////////////////////////////////////////////////////////////
511 /////////////////////////////////////////////////////////////////////
512 };// namespace solver
513 ///////////////////////////////////////////////////////////////////////
514 ///////////////////////////////////////////////////////////////////////
516 /////////////////////////////////////////////////////////////////////////