Testcase.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sstream>
00015 #include <streambuf>
00016 
00017 #include "zypp/solver/detail/Testcase.h"
00018 #include "zypp/base/Logger.h"
00019 #include "zypp/base/LogControl.h"
00020 #include "zypp/PathInfo.h"
00021 #include "zypp/Product.h"
00022 #include "zypp/Package.h"
00023 #include "zypp/Edition.h"
00024 #include "zypp/target/store/xml_escape_parser.hpp"
00025 #include "zypp/capability/VersionedCap.h"
00026 #include "zypp/base/String.h"
00027 #include "zypp/base/PtrTypes.h"
00028 
00029 
00031 namespace zypp
00032 { 
00033 
00034   namespace solver
00035   { 
00036 
00037     namespace detail
00038     { 
00039         
00040 #define TAB "\t"
00041 #define TAB2 "\t\t"
00042         
00043 using namespace std;
00044 using namespace zypp::capability;
00045 using namespace zypp::str;
00046 
00047 IMPL_PTR_TYPE(HelixResolvable); 
00048 
00049 static std::string xml_escape( const std::string &text )
00050 {
00051   iobind::parser::xml_escape_parser parser;
00052   return parser.escape(text);
00053 }
00054 
00055 static std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false )
00056 {
00057   string result;
00058   result += "<" + tag + ">";
00059 
00060   if ( escape)
00061    result += xml_escape(text);
00062   else
00063    result += text;
00064 
00065   result += "</" + tag + ">";
00066   return result;
00067 }
00068 
00069         
00070 template<class T>
00071 std::string helixXML( const T &obj ); //undefined
00072 
00073 template<> 
00074 std::string helixXML( const Edition &edition )
00075 {
00076     stringstream str;
00077     str << xml_tag_enclose(edition.version(), "version");
00078     if (!edition.release().empty())
00079         str << xml_tag_enclose(edition.release(), "release");
00080     if (edition.epoch() != Edition::noepoch)
00081         str << xml_tag_enclose(numstring(edition.epoch()), "epoch");    
00082     return str.str();
00083 }
00084 
00085 template<> 
00086 std::string helixXML( const Arch &arch )
00087 {
00088     stringstream str;
00089     str << xml_tag_enclose(arch.asString(), "arch");        
00090     return str.str();    
00091 }
00092 
00093 template<> 
00094 std::string helixXML( const Capability &cap )
00095 {
00096     stringstream str;
00097     VersionedCap::constPtr vercap = asKind<VersionedCap>(cap);
00098     if (vercap
00099         && vercap->op() != Rel::NONE
00100         && vercap->op() != Rel::ANY
00101         && !vercap->edition().version().empty() )
00102     {
00103         // version capability
00104         str << "<dep name='" << xml_escape(vercap->index()) << "' op='" << xml_escape(vercap->op().asString()) <<
00105             "' version='" << vercap->edition().version() << "'";
00106         if (!vercap->edition().release().empty())
00107             str << " release='" << vercap->edition().release() << "'";
00108         if (vercap->edition().epoch() != Edition::noepoch)
00109             str << " epoch='" << numstring(vercap->edition().epoch()) << "'";
00110     }
00111     else
00112     {
00113       str << "<dep name='" << xml_escape(cap.asString()) << "'";
00114     }
00115     
00116     str << " kind=\"" << toLower (cap.refers().asString()) << "\""
00117         << " />" << endl;
00118         
00119     return str.str();    
00120 }
00121 
00122 template<> 
00123 std::string helixXML( const CapSet &caps )
00124 {
00125     stringstream str;
00126     CapSet::iterator it = caps.begin();
00127     str << endl;
00128     for ( ; it != caps.end(); ++it)
00129     {
00130         str << TAB2 << helixXML((*it));
00131     }
00132     str << TAB;
00133     return str.str();
00134 }
00135 
00136 template<> 
00137 std::string helixXML( const Dependencies &dep )
00138 {
00139     stringstream str;
00140     if ( dep[Dep::PROVIDES].size() > 0 )
00141         str << TAB << xml_tag_enclose(helixXML(dep[Dep::PROVIDES]), "provides") << endl;
00142     if ( dep[Dep::CONFLICTS].size() > 0 )
00143         str << TAB << xml_tag_enclose(helixXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
00144     if ( dep[Dep::OBSOLETES].size() > 0 )
00145         str << TAB << xml_tag_enclose(helixXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
00146     if ( dep[Dep::FRESHENS].size() > 0 )
00147         str << TAB << xml_tag_enclose(helixXML(dep[Dep::FRESHENS]), "freshens") << endl;
00148     if ( dep[Dep::REQUIRES].size() > 0 )
00149         str << TAB << xml_tag_enclose(helixXML(dep[Dep::REQUIRES]), "requires") << endl;  
00150     if ( dep[Dep::RECOMMENDS].size() > 0 )
00151         str << TAB << xml_tag_enclose(helixXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
00152     if ( dep[Dep::ENHANCES].size() > 0 )
00153         str << TAB << xml_tag_enclose(helixXML(dep[Dep::ENHANCES]), "enhances") << endl;
00154     if ( dep[Dep::SUPPLEMENTS].size() > 0 )
00155         str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
00156     if ( dep[Dep::SUGGESTS].size() > 0 )
00157         str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUGGESTS]), "suggests") << endl;
00158     return str.str();    
00159 }
00160 
00161 std::string helixXML( const Resolvable::constPtr &resolvable )
00162 {
00163   stringstream str;
00164   if ( isKind<SystemResObject>(resolvable)
00165        || isKind<Language>(resolvable) ) {
00166       // system resolvable will be generated by the resolver
00167       // language dependencies will be written i another part
00168       return str.str();
00169   }
00170   
00171   str << "<" << toLower (resolvable->kind().asString()) << ">" << endl;
00172   str << TAB << xml_tag_enclose (resolvable->name(), "name", true) << endl;  
00173   if ( isKind<Package>(resolvable) ) {
00174       str << TAB << "<history>" << endl << TAB << "<update>" << endl;
00175       str << TAB2 << helixXML (resolvable->arch()) << endl;
00176       str << TAB2 << helixXML (resolvable->edition()) << endl;      
00177       str << TAB << "</update>" << endl << TAB << "</history>" << endl;
00178   } else {
00179       str << TAB << helixXML (resolvable->arch()) << endl;      
00180       str << TAB << helixXML (resolvable->edition()) << endl;            
00181   }
00182   str << helixXML (resolvable->deps());              
00183 
00184   str << "</" << toLower (resolvable->kind().asString()) << ">" << endl;  
00185   return str.str();
00186 }
00187 
00188 //---------------------------------------------------------------------------
00189 
00190 Testcase::Testcase()
00191     :dumpPath("/var/log/YaST2/solverTestcase")    
00192 {
00193 }
00194 
00195 Testcase::Testcase(const std::string & path)
00196     :dumpPath(path)
00197 {
00198 }
00199         
00200 
00201 Testcase::~Testcase()
00202 {
00203 }
00204 
00205 bool Testcase::createTestcase(Resolver & resolver)
00206 {
00207     PathInfo path (dumpPath);
00208 
00209     if ( !path.isExist() ) {
00210         if (zypp::filesystem::mkdir (dumpPath)!=0) {
00211             ERR << "Cannot create directory " << dumpPath << endl;
00212             return false;
00213         }
00214     } else {
00215         if (!path.isDir()) {
00216             ERR << dumpPath << " is not a directory." << endl;
00217             return false;
00218         }
00219         // remove old stuff
00220         zypp::filesystem::clean_dir (dumpPath);
00221     }
00222     
00223     zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" );
00224     zypp::base::LogControl::TmpExcessive excessive;
00225 
00226     resolver.reset(true); // true = resetting all valid solverresults
00227     resolver.resolvePool();
00228 
00229     zypp::base::LogControl::instance().logfile( "/var/log/YaST2/y2log" );    
00230 
00231     ResPool pool        = resolver.pool();
00232     RepositoryTable             repoTable;
00233     PoolItemList        items_to_install;
00234     PoolItemList        items_to_remove;
00235     PoolItemList        items_locked;    
00236     PoolItemList        language;
00237     HelixResolvable     system (dumpPath + "/solver-system.xml");    
00238 
00239     for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
00240     {
00241         Resolvable::constPtr res = it->resolvable();
00242 
00243         if (isKind<Language>(res)) {
00244             if ( it->status().isInstalled()
00245                  || it->status().isToBeInstalled()) {
00246                 language.push_back (*it);               
00247             }
00248         } else {
00249             if ( it->status().isInstalled() ) {
00250                 // system channel
00251                 system.addResolvable (res);
00252             } else {
00253                 // repo channels
00254                 ResObject::constPtr repoItem = it->resolvable();
00255                 Repository repo  = repoItem->repository();
00256                 if (repoTable.find (repo) == repoTable.end()) {
00257                     repoTable[repo] = new HelixResolvable(dumpPath + "/"
00258                                                           + numstring(repo.numericId())
00259                                                           + "-package.xml");
00260                 }
00261                 repoTable[repo]->addResolvable (res);
00262             }
00263         
00264             if ( it->status().isToBeInstalled()
00265                  && !(it->status().isBySolver())) {
00266                 items_to_install.push_back (*it);
00267             }
00268             if ( it->status().isToBeUninstalled()
00269                  && !(it->status().isBySolver())) {
00270                 items_to_remove.push_back (*it);
00271             }
00272             if ( it->status().isLocked()
00273                  && !(it->status().isBySolver())
00274                  && !isKind<SystemResObject>(res)) {
00275                 items_locked.push_back (*it);
00276             }
00277             
00278         }
00279     }
00280 
00281     // writing control file "*-test.xml"
00282 
00283     HelixControl control (dumpPath + "/solver-test.xml",
00284                           repoTable,
00285                           resolver.architecture(),
00286                           language);
00287 
00288     for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) {
00289         control.installResolvable (iter->resolvable()); 
00290     }
00291 
00292     for (PoolItemList::const_iterator iter = items_locked.begin(); iter != items_locked.end(); iter++) {
00293         control.lockResolvable (iter->resolvable());    
00294     }
00295     
00296 
00297     for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) {
00298         control.deleteResolvable (iter->resolvable());  
00299     }
00300 
00301     control.addDependencies (resolver.extraCapability(), resolver.extraConflicts());
00302 
00303     return true;
00304 }
00305 
00306 //---------------------------------------------------------------------------
00307 
00308 HelixResolvable::HelixResolvable(const std::string & path)
00309     :dumpFile (path)    
00310 {
00311     file = new ofstream(path.c_str());
00312     if (!file) {
00313         ZYPP_THROW (Exception( "Can't open " + path ) );
00314     }
00315 
00316     *file << "<channel><subchannel>" << endl;
00317 }
00318 
00319 HelixResolvable::~HelixResolvable()
00320 {
00321     *file << "</subchannel></channel>" << endl;
00322 }
00323     
00324 
00325 void HelixResolvable::addResolvable(const Resolvable::constPtr &resolvable)
00326 {
00327     *file << helixXML (resolvable);
00328 }
00329 
00330 //---------------------------------------------------------------------------
00331 
00332 HelixControl::HelixControl(const std::string & controlPath,
00333                            const RepositoryTable & repoTable,
00334                            const Arch & systemArchitecture,
00335                            const PoolItemList &languages,
00336                            const std::string & systemPath)
00337     :dumpFile (controlPath) 
00338 {
00339     file = new ofstream(controlPath.c_str());
00340     if (!file) {
00341         ZYPP_THROW (Exception( "Can't open " + controlPath ) );
00342     }
00343 
00344     *file << "<?xml version=\"1.0\"?>" << endl
00345           << "<!-- testcase generated by YaST -->" << endl
00346           << "<test>" << endl
00347           << "<setup arch=\"" << systemArchitecture << "\">" << endl
00348           << TAB << "<system file=\"" << systemPath << "\"/>" << endl;
00349     for ( RepositoryTable::const_iterator it = repoTable.begin();
00350           it != repoTable.end(); ++it ) {
00351         Repository repo = it->first;
00352         *file << TAB << "<channel file=\"" << numstring(repo.numericId())
00353               << "-package.xml\" name=\"" << numstring(repo.numericId())
00354               << "\" />" << endl;
00355     }
00356     for (PoolItemList::const_iterator iter = languages.begin(); iter != languages.end(); iter++) {
00357         *file << TAB << "<locale name=\"" <<  iter->resolvable()->name()
00358               << "\" />" << endl;
00359     }    
00360     *file << "</setup>" << endl
00361           << "<trial>" << endl
00362           << "<showpool all=\"yes\"/>" << endl
00363           << "<establish/>" << endl
00364           << "<showpool all=\"true\" prefix=\">!> ESTABLISHED:\"/>" << endl;
00365 }
00366 
00367 HelixControl::HelixControl()
00368     :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
00369 {
00370     HelixControl (dumpFile);
00371 }
00372 
00373 HelixControl::~HelixControl()
00374 {
00375     *file << "</trial>" << endl
00376           << "</test>" << endl;
00377 }
00378 
00379 void HelixControl::installResolvable(const ResObject::constPtr &resObject)
00380 {
00381     Repository repo  = resObject->repository();
00382     *file << "<install channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
00383           << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
00384           << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\"" 
00385           << "/>" << endl;
00386 }
00387 
00388 void HelixControl::lockResolvable(const ResObject::constPtr &resObject)
00389 {
00390     Repository repo  = resObject->repository();
00391     *file << "<lock channel=\"" << numstring(repo.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
00392           << " name=\"" << resObject->name() << "\"" << " arch=\"" << resObject->arch().asString() << "\""
00393           << " version=\"" << resObject->edition().version() << "\"" << " release=\"" << resObject->edition().release() << "\"" 
00394           << "/>" << endl;
00395 }
00396     
00397 void HelixControl::deleteResolvable(const ResObject::constPtr &resObject)
00398 {
00399     Repository repo  = resObject->repository();    
00400     *file << "<uninstall " << " kind=\"" << toLower (resObject->kind().asString()) << "\""
00401           << " name=\"" << resObject->name() << "\"" << "/>" << endl;    
00402 }
00403 
00404 void HelixControl::addDependencies (const CapSet & capRequire, const CapSet & capConflict)
00405 {
00406     for (CapSet::const_iterator iter = capRequire.begin(); iter != capRequire.end(); iter++) {
00407         *file << "<addRequire " << " kind=\"" << toLower (iter->kind().asString()) << "\""
00408           << " name=\"" << iter->asString() << "\"" << "/>" << endl;    
00409     }
00410     for (CapSet::const_iterator iter = capConflict.begin(); iter != capConflict.end(); iter++) {
00411         *file << "<addConflict " << " kind=\"" << toLower (iter->kind().asString()) << "\""
00412           << " name=\"" << iter->asString() << "\"" << "/>" << endl;    
00413     }    
00414 }
00415 
00416 
00418     };// namespace detail
00421   };// namespace solver
00424 };// namespace zypp

Generated on Tue Sep 25 19:23:08 2007 for libzypp by  doxygen 1.5.3