From e7928f72e3e31b36baccb82733d14e9b975383ac Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Tue, 24 Oct 2006 17:32:54 +0000 Subject: [PATCH] generating testcases from the pool --- zypp/solver/detail/Testcase.cc | 275 ++++++++++++++++++++++++++++++++++++++++- zypp/solver/detail/Testcase.h | 89 ++++++++++++- 2 files changed, 356 insertions(+), 8 deletions(-) diff --git a/zypp/solver/detail/Testcase.cc b/zypp/solver/detail/Testcase.cc index 4d2779d..ea79761 100644 --- a/zypp/solver/detail/Testcase.cc +++ b/zypp/solver/detail/Testcase.cc @@ -9,10 +9,23 @@ /** \file zypp/solver/detail/Testcase.cc * */ +#include +#include +#include +#include + #include "zypp/solver/detail/Testcase.h" #include "zypp/base/Logger.h" #include "zypp/base/LogControl.h" #include "zypp/PathInfo.h" +#include "zypp/Product.h" +#include "zypp/Package.h" +#include "zypp/Edition.h" +#include "zypp/target/store/xml_escape_parser.hpp" +#include "zypp/capability/VersionedCap.h" +#include "zypp/base/String.h" +#include "zypp/base/PtrTypes.h" + ///////////////////////////////////////////////////////////////////////// namespace zypp @@ -23,13 +36,138 @@ namespace zypp ///////////////////////////////////////////////////////////////////// namespace detail { /////////////////////////////////////////////////////////////////// - + +#define TAB "\t" +#define TAB2 "\t\t" + using namespace std; +using namespace zypp::capability; +using namespace zypp::str; + +IMPL_PTR_TYPE(HelixResolvable); + +static std::string xml_escape( const std::string &text ) +{ + iobind::parser::xml_escape_parser parser; + return parser.escape(text); +} + +static std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false ) +{ + string result; + result += "<" + tag + ">"; + + if ( escape) + result += xml_escape(text); + else + result += text; + + result += ""; + return result; +} + + +template +std::string helixXML( const T &obj ); //undefined + +template<> +std::string helixXML( const Edition &edition ) +{ + stringstream str; + str << xml_tag_enclose(edition.version(), "version") + << xml_tag_enclose(edition.release(), "release") + << xml_tag_enclose(numstring(edition.epoch()), "epoch"); + return str.str(); +} + +template<> +std::string helixXML( const Arch &arch ) +{ + stringstream str; + str << xml_tag_enclose(arch.asString(), "arch"); + return str.str(); +} + +template<> +std::string helixXML( const Capability &cap ) +{ + stringstream str; + if (isKind(cap) + && cap.op() != Rel::NONE + && cap.op() != Rel::ANY) { + // version capability + str << "" << endl; + } else { + // anything else + str << "" << endl; + } + return str.str(); +} + +template<> +std::string helixXML( const CapSet &caps ) +{ + stringstream str; + CapSet::iterator it = caps.begin(); + str << endl; + for ( ; it != caps.end(); ++it) + { + str << TAB2 << helixXML((*it)); + } + str << TAB; + return str.str(); +} + +template<> +std::string helixXML( const Dependencies &dep ) +{ + stringstream str; + if ( dep[Dep::PROVIDES].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::PROVIDES]), "provides") << endl; + if ( dep[Dep::CONFLICTS].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::CONFLICTS]), "conflicts") << endl; + if ( dep[Dep::OBSOLETES].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::OBSOLETES]), "obsoletes") << endl; + if ( dep[Dep::FRESHENS].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::FRESHENS]), "freshens") << endl; + if ( dep[Dep::REQUIRES].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::REQUIRES]), "requires") << endl; + if ( dep[Dep::RECOMMENDS].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::RECOMMENDS]), "recommends") << endl; + if ( dep[Dep::ENHANCES].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::ENHANCES]), "enhances") << endl; + if ( dep[Dep::SUPPLEMENTS].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl; + if ( dep[Dep::SUGGESTS].size() > 0 ) + str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUGGESTS]), "suggests") << endl; + return str.str(); +} + +std::string helixXML( const Resolvable::constPtr &resolvable ) +{ + stringstream str; + str << "<" << toLower (resolvable->kind().asString()) << ">" << endl; + str << TAB << xml_tag_enclose (resolvable->name(), "name") << endl; + if ( isKind(resolvable) ) { + str << TAB << "" << endl << TAB << "" << endl; + str << TAB2 << helixXML (resolvable->arch()) << endl; + str << TAB2 << helixXML (resolvable->edition()) << endl; + str << TAB << "" << endl << TAB << "" << endl; + } else { + str << TAB << helixXML (resolvable->arch()) << endl; + str << TAB << helixXML (resolvable->edition()) << endl; + } + str << helixXML (resolvable->deps()); + + str << "kind().asString()) << ">" << endl; + return str.str(); +} //--------------------------------------------------------------------------- Testcase::Testcase() - :dumpPath("/var/log/YaST2/solverTestcase") + :dumpPath("/var/log/YaST2/solverTestcase") { } @@ -62,10 +200,141 @@ bool Testcase::createTestcase(Resolver & resolver) zypp::base::LogControl::TmpExcessive excessive; // ZYPP_FULLLOG=1 resolver.resolveDependencies(); - + + ResPool pool = resolver.pool(); + SourceTable sourceTable; + PoolItemList items_to_install; + PoolItemList items_to_remove; + + HelixResolvable system (dumpPath + "/solver-system.xml"); + + for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it ) + { + Resolvable::constPtr res = it->resolvable(); + + if ( it->status().isInstalled() ) { + // system channel + system.addResolvable (res); + } else { + // source channels + ResObject::constPtr sourceItem = it->resolvable(); + Source_Ref source = sourceItem->source(); + if (sourceTable.find (source) == sourceTable.end()) { + sourceTable[source] = new HelixResolvable(dumpPath + "/" + + numstring(source.numericId()) + + "-package.xml"); + } + sourceTable[source]->addResolvable (res); + } + + if ( it->status().isToBeInstalled() + && !(it->status().isBySolver())) { + items_to_install.push_back (*it); + } + if ( it->status().isToBeUninstalled() + && !(it->status().isBySolver())) { + items_to_remove.push_back (*it); + } + } + + // writing control file "*-test.xml" + + HelixControl control (dumpPath + "/solver-test.xml", + sourceTable); + + for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) { + control.installResolvable (iter->resolvable()); + } + + for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) { + control.deleteResolvable (iter->resolvable()); + } + return true; } +//--------------------------------------------------------------------------- + +HelixResolvable::HelixResolvable(const std::string & path) + :dumpFile (path) +{ + file = new ofstream(path.c_str()); + if (!file) { + ZYPP_THROW (Exception( "Can't open " + path ) ); + } + + *file << "" << endl; +} + +HelixResolvable::~HelixResolvable() +{ + *file << "" << endl; +} + + +void HelixResolvable::addResolvable(const Resolvable::constPtr &resolvable) +{ + *file << helixXML (resolvable); +} + +//--------------------------------------------------------------------------- + +HelixControl::HelixControl(const std::string & controlPath, + const SourceTable & sourceTable, + const std::string & systemPath) + :dumpFile (controlPath) +{ + file = new ofstream(controlPath.c_str()); + if (!file) { + ZYPP_THROW (Exception( "Can't open " + controlPath ) ); + } + + *file << "" << endl + << "" << endl + << "" << endl + << "" << endl + << TAB << "" << endl; + for ( SourceTable::const_iterator it = sourceTable.begin(); + it != sourceTable.end(); ++it ) { + Source_Ref source = it->first; + *file << TAB << "" << endl; + } + *file << "" << endl + << "" << endl + << "" << endl + << "" << endl + << "!> ESTABLISHED:\"/>" << endl; +} + +HelixControl::HelixControl() + :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml") +{ + HelixControl (dumpFile); +} + +HelixControl::~HelixControl() +{ + *file << "" << endl + << "" << endl; +} + +void HelixControl::installResolvable(const ResObject::constPtr &resObject) +{ + Source_Ref source = resObject->source(); + *file << "kind().asString()) << "\"" + << " name=\"" << resObject->name() << "\"" << "/>" << endl; +} + +void HelixControl::deleteResolvable(const ResObject::constPtr &resObject) +{ + Source_Ref source = resObject->source(); + *file << "kind().asString()) << "\"" + << " name=\"" << resObject->name() << "\"" << "/>" << endl; +} + + /////////////////////////////////////////////////////////////////// };// namespace detail ///////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Testcase.h b/zypp/solver/detail/Testcase.h index 0688ad4..7307a3d 100644 --- a/zypp/solver/detail/Testcase.h +++ b/zypp/solver/detail/Testcase.h @@ -15,8 +15,12 @@ #include #include +#include "zypp/base/ReferenceCounted.h" +#include "zypp/base/NonCopyable.h" +#include "zypp/base/PtrTypes.h" #include "zypp/solver/detail/Resolver.h" + ///////////////////////////////////////////////////////////////////////// namespace zypp { /////////////////////////////////////////////////////////////////////// @@ -27,6 +31,81 @@ namespace zypp namespace detail { /////////////////////////////////////////////////////////////////// + +template +std::string helixXML( const T &obj ); //undefined + +template<> +std::string helixXML( const Edition &edition ); + +template<> +std::string helixXML( const Arch &arch ); + +template<> +std::string helixXML( const Capability &cap ); + +template<> +std::string helixXML( const CapSet &caps ); + +template<> +std::string helixXML( const Dependencies &dep ); + +template<> +std::string helixXML( const Resolvable::constPtr &resolvable ); + + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : HelixResolvable +/** + * Creates a file in helix format which includes all available + * or installed packages,patches,selections..... + **/ +class HelixResolvable : public base::ReferenceCounted, private base::NonCopyable{ + + private: + std::string dumpFile; // Path of the generated testcase + std::ofstream *file; + + public: + HelixResolvable (const std::string & path); + ~HelixResolvable (); + + void addResolvable (const Resolvable::constPtr &resolvable); + std::string filename () { return dumpFile; } +}; + +DEFINE_PTR_TYPE(HelixResolvable); +typedef std::map SourceTable; + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : HelixControl +/** + * Creates a file in helix format which contains all controll + * action of a testcase ( file is known as *-test.xml) + **/ +class HelixControl { + + private: + std::string dumpFile; // Path of the generated testcase + std::ofstream *file; + + public: + HelixControl (const std::string & controlPath, + const SourceTable & sourceTable, + const std::string & systemPath = "solver-system.xml"); + HelixControl (); + ~HelixControl (); + + void installResolvable (const ResObject::constPtr &resObject); + void deleteResolvable (const ResObject::constPtr &resObject); + std::string filename () { return dumpFile; } +}; + + + + /////////////////////////////////////////////////////////////////// // // CLASS NAME : Testcase @@ -37,17 +116,17 @@ class Testcase { private: std::string dumpPath; // Path of the generated testcase - public: - Testcase(const std::string & path); - Testcase(); - ~Testcase(); + Testcase (const std::string & path); + Testcase (); + ~Testcase (); - bool createTestcase(Resolver & resolver); + bool createTestcase (Resolver & resolver); }; + /////////////////////////////////////////////////////////////////// };// namespace detail ///////////////////////////////////////////////////////////////////// -- 2.7.4