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/capability/VersionedCap.h"
26 #include "zypp/base/String.h"
27 #include "zypp/base/PtrTypes.h"
30 /////////////////////////////////////////////////////////////////////////
32 { ///////////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////////
36 /////////////////////////////////////////////////////////////////////
38 { ///////////////////////////////////////////////////////////////////
44 using namespace zypp::capability;
45 using namespace zypp::str;
47 IMPL_PTR_TYPE(HelixResolvable);
49 static std::string xml_escape( const std::string &text )
51 iobind::parser::xml_escape_parser parser;
52 return parser.escape(text);
55 static std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false )
58 result += "<" + tag + ">";
61 result += xml_escape(text);
65 result += "</" + tag + ">";
71 std::string helixXML( const T &obj ); //undefined
74 std::string helixXML( const Edition &edition )
77 str << xml_tag_enclose(edition.version(), "version");
78 if (!edition.release().empty())
79 str << xml_tag_enclose(edition.release(), "release");
80 if (edition.epoch() != Edition::noepoch)
81 str << xml_tag_enclose(numstring(edition.epoch()), "epoch");
86 std::string helixXML( const Arch &arch )
89 str << xml_tag_enclose(arch.asString(), "arch");
94 std::string helixXML( const Capability &cap )
97 VersionedCap::constPtr vercap = asKind<VersionedCap>(cap);
99 && vercap->op() != Rel::NONE
100 && vercap->op() != Rel::ANY
101 && !vercap->edition().version().empty() )
103 // version capability
104 str << "<dep name='" << xml_escape(vercap->index()) << "' op='" << xml_escape(vercap->op().asString()) <<
105 "' version='" << vercap->edition().version() << "'";
106 if (!vercap->edition().release().empty())
107 str << " release='" << vercap->edition().release() << "'";
108 if (vercap->edition().epoch() != Edition::noepoch)
109 str << " epoch='" << numstring(vercap->edition().epoch()) << "'";
113 str << "<dep name='" << xml_escape(cap.asString()) << "'";
116 str << " kind=\"" << toLower (cap.refers().asString()) << "\""
123 std::string helixXML( const CapSet &caps )
126 CapSet::iterator it = caps.begin();
128 for ( ; it != caps.end(); ++it)
130 str << TAB2 << helixXML((*it));
137 std::string helixXML( const Dependencies &dep )
140 if ( dep[Dep::PROVIDES].size() > 0 )
141 str << TAB << xml_tag_enclose(helixXML(dep[Dep::PROVIDES]), "provides") << endl;
142 if ( dep[Dep::CONFLICTS].size() > 0 )
143 str << TAB << xml_tag_enclose(helixXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
144 if ( dep[Dep::OBSOLETES].size() > 0 )
145 str << TAB << xml_tag_enclose(helixXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
146 if ( dep[Dep::FRESHENS].size() > 0 )
147 str << TAB << xml_tag_enclose(helixXML(dep[Dep::FRESHENS]), "freshens") << endl;
148 if ( dep[Dep::REQUIRES].size() > 0 )
149 str << TAB << xml_tag_enclose(helixXML(dep[Dep::REQUIRES]), "requires") << endl;
150 if ( dep[Dep::RECOMMENDS].size() > 0 )
151 str << TAB << xml_tag_enclose(helixXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
152 if ( dep[Dep::ENHANCES].size() > 0 )
153 str << TAB << xml_tag_enclose(helixXML(dep[Dep::ENHANCES]), "enhances") << endl;
154 if ( dep[Dep::SUPPLEMENTS].size() > 0 )
155 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
156 if ( dep[Dep::SUGGESTS].size() > 0 )
157 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUGGESTS]), "suggests") << endl;
161 std::string helixXML( const Resolvable::constPtr &resolvable )
164 if ( isKind<SystemResObject>(resolvable)
165 || isKind<Language>(resolvable) ) {
166 // system resolvable will be generated by the resolver
167 // language dependencies will be written i another part
171 str << "<" << toLower (resolvable->kind().asString()) << ">" << endl;
172 str << TAB << xml_tag_enclose (resolvable->name(), "name", 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->deps());
184 str << "</" << toLower (resolvable->kind().asString()) << ">" << endl;
188 //---------------------------------------------------------------------------
191 :dumpPath("/var/log/YaST2/solverTestcase")
195 Testcase::Testcase(const std::string & path)
201 Testcase::~Testcase()
205 bool Testcase::createTestcase(Resolver & resolver)
207 PathInfo path (dumpPath);
209 if ( !path.isExist() ) {
210 if (zypp::filesystem::mkdir (dumpPath)!=0) {
211 ERR << "Cannot create directory " << dumpPath << endl;
216 ERR << dumpPath << " is not a directory." << endl;
220 zypp::filesystem::clean_dir (dumpPath);
223 zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" );
224 zypp::base::LogControl::TmpExcessive excessive;
226 resolver.reset(true); // true = resetting all valid solverresults
227 resolver.resolvePool();
229 zypp::base::LogControl::instance().logfile( "/var/log/YaST2/y2log" );
231 ResPool pool = resolver.pool();
232 RepositoryTable repoTable;
233 PoolItemList items_to_install;
234 PoolItemList items_to_remove;
235 PoolItemList language;
236 HelixResolvable system (dumpPath + "/solver-system.xml");
238 for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
240 Resolvable::constPtr res = it->resolvable();
242 if (isKind<Language>(res)) {
243 if ( it->status().isInstalled()
244 || it->status().isToBeInstalled()) {
245 language.push_back (*it);
248 if ( it->status().isInstalled() ) {
250 system.addResolvable (res);
253 ResObject::constPtr repoItem = it->resolvable();
254 Repository repo = repoItem->repository();
255 if (repoTable.find (repo) == repoTable.end()) {
256 repoTable[repo] = new HelixResolvable(dumpPath + "/"
257 + numstring(repo.numericId())
260 repoTable[repo]->addResolvable (res);
263 if ( it->status().isToBeInstalled()
264 && !(it->status().isBySolver())) {
265 items_to_install.push_back (*it);
267 if ( it->status().isToBeUninstalled()
268 && !(it->status().isBySolver())) {
269 items_to_remove.push_back (*it);
274 // writing control file "*-test.xml"
276 HelixControl control (dumpPath + "/solver-test.xml",
278 resolver.architecture(),
281 for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) {
282 control.installResolvable (iter->resolvable());
285 for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) {
286 control.deleteResolvable (iter->resolvable());
289 control.addDependencies (resolver.extraCapability(), resolver.extraConflicts());
294 //---------------------------------------------------------------------------
296 HelixResolvable::HelixResolvable(const std::string & path)
299 file = new ofstream(path.c_str());
301 ZYPP_THROW (Exception( "Can't open " + path ) );
304 *file << "<channel><subchannel>" << endl;
307 HelixResolvable::~HelixResolvable()
309 *file << "</subchannel></channel>" << endl;
313 void HelixResolvable::addResolvable(const Resolvable::constPtr &resolvable)
315 *file << helixXML (resolvable);
318 //---------------------------------------------------------------------------
320 HelixControl::HelixControl(const std::string & controlPath,
321 const RepositoryTable & repoTable,
322 const Arch & systemArchitecture,
323 const PoolItemList &languages,
324 const std::string & systemPath)
325 :dumpFile (controlPath)
327 file = new ofstream(controlPath.c_str());
329 ZYPP_THROW (Exception( "Can't open " + controlPath ) );
332 *file << "<?xml version=\"1.0\"?>" << endl
333 << "<!-- testcase generated by YaST -->" << endl
335 << "<setup arch=\"" << systemArchitecture << "\">" << endl
336 << TAB << "<system file=\"" << systemPath << "\"/>" << endl;
337 for ( RepositoryTable::const_iterator it = repoTable.begin();
338 it != repoTable.end(); ++it ) {
339 Repository repo = it->first;
340 *file << TAB << "<channel file=\"" << numstring(repo.numericId())
341 << "-package.xml\" name=\"" << numstring(repo.numericId())
344 for (PoolItemList::const_iterator iter = languages.begin(); iter != languages.end(); iter++) {
345 *file << TAB << "<locale name=\"" << iter->resolvable()->name()
348 *file << "</setup>" << endl
350 << "<showpool all=\"yes\"/>" << endl
351 << "<establish/>" << endl
352 << "<showpool all=\"true\" prefix=\">!> ESTABLISHED:\"/>" << endl;
355 HelixControl::HelixControl()
356 :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
358 HelixControl (dumpFile);
361 HelixControl::~HelixControl()
363 *file << "</trial>" << endl
364 << "</test>" << endl;
367 void HelixControl::installResolvable(const ResObject::constPtr &resObject)
369 Repository repo = resObject->repository();
370 *file << "<install channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
371 << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
372 << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\""
373 << " edition=\"" << resObject->edition().asString() << "\"" << "/>" << endl;
376 void HelixControl::deleteResolvable(const ResObject::constPtr &resObject)
378 Repository repo = resObject->repository();
379 *file << "<uninstall " << " kind=\"" << toLower (resObject->kind().asString()) << "\""
380 << " name=\"" << resObject->name() << "\"" << "/>" << endl;
383 void HelixControl::addDependencies (const CapSet & capRequire, const CapSet & capConflict)
385 for (CapSet::const_iterator iter = capRequire.begin(); iter != capRequire.end(); iter++) {
386 *file << "<addRequire " << " kind=\"" << toLower (iter->kind().asString()) << "\""
387 << " name=\"" << iter->asString() << "\"" << "/>" << endl;
389 for (CapSet::const_iterator iter = capConflict.begin(); iter != capConflict.end(); iter++) {
390 *file << "<addConflict " << " kind=\"" << toLower (iter->kind().asString()) << "\""
391 << " name=\"" << iter->asString() << "\"" << "/>" << endl;
396 ///////////////////////////////////////////////////////////////////
397 };// namespace detail
398 /////////////////////////////////////////////////////////////////////
399 /////////////////////////////////////////////////////////////////////
400 };// namespace solver
401 ///////////////////////////////////////////////////////////////////////
402 ///////////////////////////////////////////////////////////////////////
404 /////////////////////////////////////////////////////////////////////////