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/PathInfo.h"
21 #include "zypp/Product.h"
22 #include "zypp/Package.h"
23 #include "zypp/Edition.h"
24 #include "zypp/target/store/xml_escape_parser.hpp"
25 #include "zypp/base/String.h"
26 #include "zypp/base/PtrTypes.h"
27 #include "zypp/Capabilities.h"
30 /////////////////////////////////////////////////////////////////////////
32 { ///////////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////
36 Arch defaultArchitecture();
37 /////////////////////////////////////////////////////////////////
38 } // namespace zypp_detail
39 ///////////////////////////////////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////////
42 { /////////////////////////////////////////////////////////////////////
43 /////////////////////////////////////////////////////////////////////
45 { ///////////////////////////////////////////////////////////////////
51 using namespace zypp::str;
53 IMPL_PTR_TYPE(HelixResolvable);
55 static std::string xml_escape( const std::string &text )
57 iobind::parser::xml_escape_parser parser;
58 return parser.escape(text);
61 static std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false )
64 result += "<" + tag + ">";
67 result += xml_escape(text);
71 result += "</" + tag + ">";
77 std::string helixXML( const T &obj ); //undefined
80 std::string helixXML( const Edition &edition )
83 str << xml_tag_enclose(edition.version(), "version");
84 if (!edition.release().empty())
85 str << xml_tag_enclose(edition.release(), "release");
86 if (edition.epoch() != Edition::noepoch)
87 str << xml_tag_enclose(numstring(edition.epoch()), "epoch");
92 std::string helixXML( const Arch &arch )
95 str << xml_tag_enclose(arch.asString(), "arch");
100 std::string helixXML( const Capability &cap )
103 str << "<dep name='" << xml_escape(cap.asString()) << "' />" << endl;
109 std::string helixXML( const Capabilities &caps )
112 Capabilities::const_iterator it = caps.begin();
114 for ( ; it != caps.end(); ++it)
116 str << TAB2 << helixXML((*it));
123 std::string helixXML( const CapabilitySet &caps )
126 CapabilitySet::const_iterator it = caps.begin();
128 for ( ; it != caps.end(); ++it)
130 str << TAB2 << helixXML((*it));
138 std::string helixXML( const Dependencies &dep )
141 if ( dep[Dep::PROVIDES].size() > 0 )
142 str << TAB << xml_tag_enclose(helixXML(dep[Dep::PROVIDES]), "provides") << endl;
143 if ( dep[Dep::CONFLICTS].size() > 0 )
144 str << TAB << xml_tag_enclose(helixXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
145 if ( dep[Dep::OBSOLETES].size() > 0 )
146 str << TAB << xml_tag_enclose(helixXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
147 if ( dep[Dep::FRESHENS].size() > 0 )
148 str << TAB << xml_tag_enclose(helixXML(dep[Dep::FRESHENS]), "freshens") << endl;
149 if ( dep[Dep::REQUIRES].size() > 0 )
150 str << TAB << xml_tag_enclose(helixXML(dep[Dep::REQUIRES]), "requires") << endl;
151 if ( dep[Dep::RECOMMENDS].size() > 0 )
152 str << TAB << xml_tag_enclose(helixXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
153 if ( dep[Dep::ENHANCES].size() > 0 )
154 str << TAB << xml_tag_enclose(helixXML(dep[Dep::ENHANCES]), "enhances") << endl;
155 if ( dep[Dep::SUPPLEMENTS].size() > 0 )
156 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
157 if ( dep[Dep::SUGGESTS].size() > 0 )
158 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUGGESTS]), "suggests") << endl;
162 std::string helixXML( const PoolItem_Ref &item )
164 const Resolvable::constPtr resolvable = item.resolvable();
166 if ( isKind<Language>(resolvable) ) {
167 // language dependencies will be written in another part
171 str << "<" << toLower (resolvable->kind().asString()) << ">" << endl;
172 str << TAB << xml_tag_enclose (resolvable->name(), "name", true) << endl;
173 str << TAB << xml_tag_enclose (item->vendor(), "vendor", true) << endl;
174 if ( isKind<Package>(resolvable) ) {
175 str << TAB << "<history>" << endl << TAB << "<update>" << endl;
176 str << TAB2 << helixXML (resolvable->arch()) << endl;
177 str << TAB2 << helixXML (resolvable->edition()) << endl;
178 str << TAB << "</update>" << endl << TAB << "</history>" << endl;
180 str << TAB << helixXML (resolvable->arch()) << endl;
181 str << TAB << helixXML (resolvable->edition()) << endl;
183 str << helixXML (resolvable->deps());
185 str << "</" << toLower (resolvable->kind().asString()) << ">" << endl;
189 //---------------------------------------------------------------------------
192 :dumpPath("/var/log/YaST2/solverTestcase")
196 Testcase::Testcase(const std::string & path)
202 Testcase::~Testcase()
207 bool Testcase::createTestcase(Resolver & resolver, bool dumpPool, bool runSolver)
209 PathInfo path (dumpPath);
211 if ( !path.isExist() ) {
212 if (zypp::filesystem::mkdir (dumpPath)!=0) {
213 ERR << "Cannot create directory " << dumpPath << endl;
218 ERR << dumpPath << " is not a directory." << endl;
221 // remove old stuff if pool will be dump
223 zypp::filesystem::clean_dir (dumpPath);
227 zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" );
228 zypp::base::LogControl::TmpExcessive excessive;
230 resolver.reset(true); // true = resetting all valid solverresults
231 resolver.resolvePool();
233 zypp::base::LogControl::instance().logfile( "/var/log/YaST2/y2log" );
236 ResPool pool = resolver.pool();
237 RepositoryTable repoTable;
238 PoolItemList items_to_install;
239 PoolItemList items_to_remove;
240 PoolItemList items_locked;
241 PoolItemList items_keep;
242 PoolItemList language;
243 HelixResolvable_Ptr system = NULL;
246 system = new HelixResolvable(dumpPath + "/solver-system.xml");
248 for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
250 Resolvable::constPtr res = it->resolvable();
252 if (isKind<Language>(res)) {
253 if ( it->status().isInstalled()
254 || it->status().isToBeInstalled()) {
255 language.push_back (*it);
258 if ( system && it->status().isInstalled() ) {
260 system->addResolvable (*it);
263 ResObject::constPtr repoItem = it->resolvable();
264 Repository repo = repoItem->repository();
266 if (repoTable.find (repo) == repoTable.end()) {
267 repoTable[repo] = new HelixResolvable(dumpPath + "/"
268 + numstring(repo.numericId())
271 repoTable[repo]->addResolvable (*it);
275 if ( it->status().isToBeInstalled()
276 && !(it->status().isBySolver())) {
277 items_to_install.push_back (*it);
279 if ( it->status().isKept()
280 && !(it->status().isBySolver())) {
281 items_keep.push_back (*it);
283 if ( it->status().isToBeUninstalled()
284 && !(it->status().isBySolver())) {
285 items_to_remove.push_back (*it);
287 if ( it->status().isLocked()
288 && !(it->status().isBySolver())) {
289 items_locked.push_back (*it);
294 // writing control file "*-test.xml"
296 HelixControl control (dumpPath + "/solver-test.xml",
298 zypp_detail::defaultArchitecture(),
301 for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) {
302 control.installResolvable (iter->resolvable(), iter->status());
305 for (PoolItemList::const_iterator iter = items_locked.begin(); iter != items_locked.end(); iter++) {
306 control.lockResolvable (iter->resolvable(), iter->status());
309 for (PoolItemList::const_iterator iter = items_keep.begin(); iter != items_keep.end(); iter++) {
310 control.keepResolvable (iter->resolvable(), iter->status());
313 for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) {
314 control.deleteResolvable (iter->resolvable(), iter->status());
317 control.addDependencies (resolver.extraRequires(), resolver.extraConflicts());
322 //---------------------------------------------------------------------------
324 HelixResolvable::HelixResolvable(const std::string & path)
327 file = new ofgzstream(path.c_str());
329 ZYPP_THROW (Exception( "Can't open " + path ) );
332 *file << "<channel><subchannel>" << endl;
335 HelixResolvable::~HelixResolvable()
337 *file << "</subchannel></channel>" << endl;
341 void HelixResolvable::addResolvable(const PoolItem_Ref item)
343 *file << helixXML (item);
346 //---------------------------------------------------------------------------
348 HelixControl::HelixControl(const std::string & controlPath,
349 const RepositoryTable & repoTable,
350 const Arch & systemArchitecture,
351 const PoolItemList &languages,
352 const std::string & systemPath)
353 :dumpFile (controlPath)
355 file = new ofstream(controlPath.c_str());
357 ZYPP_THROW (Exception( "Can't open " + controlPath ) );
360 *file << "<?xml version=\"1.0\"?>" << endl
361 << "<!-- testcase generated by YaST -->" << endl
363 << "<setup arch=\"" << systemArchitecture << "\">" << endl
364 << TAB << "<system file=\"" << systemPath << "\"/>" << endl << endl;
365 for ( RepositoryTable::const_iterator it = repoTable.begin();
366 it != repoTable.end(); ++it ) {
367 Repository repo = it->first;
368 *file << TAB << "<!-- " << endl
369 << TAB << "- alias : " << repo.info().alias() << endl;
370 for ( RepoInfo::urls_const_iterator itUrl = repo.info().baseUrlsBegin();
371 itUrl != repo.info().baseUrlsEnd();
374 *file << TAB << "- url : " << *itUrl << endl;
376 *file << TAB << "- path : " << repo.info().path() << endl;
377 *file << TAB << "- type : " << repo.info().type() << endl;
378 *file << TAB << " -->" << endl;
380 *file << TAB << "<channel file=\"" << numstring(repo.numericId())
381 << "-package.xml\" name=\"" << numstring(repo.numericId())
382 << "\" />" << endl << endl;
384 for (PoolItemList::const_iterator iter = languages.begin(); iter != languages.end(); iter++) {
385 *file << TAB << "<locale name=\"" << iter->resolvable()->name()
388 *file << "</setup>" << endl
390 << "<showpool all=\"yes\"/>" << endl
391 << "<establish/>" << endl
392 << "<showpool all=\"true\" prefix=\">!> ESTABLISHED:\"/>" << endl;
395 HelixControl::HelixControl()
396 :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
398 HelixControl (dumpFile);
401 HelixControl::~HelixControl()
403 *file << "</trial>" << endl
404 << "</test>" << endl;
407 void HelixControl::installResolvable(const ResObject::constPtr &resObject,
408 const ResStatus &status)
410 Repository repo = resObject->repository();
411 *file << "<install channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
412 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
413 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
414 << " status=\"" << status << "\""
418 void HelixControl::lockResolvable(const ResObject::constPtr &resObject,
419 const ResStatus &status)
421 Repository repo = resObject->repository();
422 *file << "<lock channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
423 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
424 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
425 << " status=\"" << status << "\""
429 void HelixControl::keepResolvable(const ResObject::constPtr &resObject,
430 const ResStatus &status)
432 Repository repo = resObject->repository();
433 *file << "<keep channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
434 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
435 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
436 << " status=\"" << status << "\""
440 void HelixControl::deleteResolvable(const ResObject::constPtr &resObject,
441 const ResStatus &status)
443 Repository repo = resObject->repository();
444 *file << "<uninstall " << " kind=\"" << toLower (resObject->kind().asString()) << "\""
445 << " name=\"" << resObject->name() << "\""
446 << " status=\"" << status << "\""
450 void HelixControl::addDependencies (const CapabilitySet & capRequire, const CapabilitySet & capConflict)
452 for (CapabilitySet::const_iterator iter = capRequire.begin(); iter != capRequire.end(); iter++) {
453 *file << "<addRequire " << " name=\"" << iter->asString() << "\"" << "/>" << endl;
455 for (CapabilitySet::const_iterator iter = capConflict.begin(); iter != capConflict.end(); iter++) {
456 *file << "<addConflict " << " name=\"" << iter->asString() << "\"" << "/>" << endl;
461 ///////////////////////////////////////////////////////////////////
462 };// namespace detail
463 /////////////////////////////////////////////////////////////////////
464 /////////////////////////////////////////////////////////////////////
465 };// namespace solver
466 ///////////////////////////////////////////////////////////////////////
467 ///////////////////////////////////////////////////////////////////////
469 /////////////////////////////////////////////////////////////////////////