00001
00002
00003
00004
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 );
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 if (isKind<VersionedCap>(cap)
00098 && cap.op() != Rel::NONE
00099 && cap.op() != Rel::ANY
00100 && !cap.edition().version().empty()) {
00101
00102 str << "<dep name='" << xml_escape(cap.index()) << "' op='" << xml_escape(cap.op().asString()) <<
00103 "' version='" << cap.edition().version() << "'";
00104 if (!cap.edition().release().empty())
00105 str << " release='" << cap.edition().release() << "'";
00106 if (cap.edition().epoch() != Edition::noepoch)
00107 str << " epoch='" << numstring(cap.edition().epoch()) << "'";
00108 } else {
00109
00110 str << "<dep name='" << xml_escape(cap.asString()) << "'";
00111 }
00112 str << " kind=\"" << toLower (cap.refers().asString()) << "\""
00113 << " />" << endl;
00114
00115 return str.str();
00116 }
00117
00118 template<>
00119 std::string helixXML( const CapSet &caps )
00120 {
00121 stringstream str;
00122 CapSet::iterator it = caps.begin();
00123 str << endl;
00124 for ( ; it != caps.end(); ++it)
00125 {
00126 str << TAB2 << helixXML((*it));
00127 }
00128 str << TAB;
00129 return str.str();
00130 }
00131
00132 template<>
00133 std::string helixXML( const Dependencies &dep )
00134 {
00135 stringstream str;
00136 if ( dep[Dep::PROVIDES].size() > 0 )
00137 str << TAB << xml_tag_enclose(helixXML(dep[Dep::PROVIDES]), "provides") << endl;
00138 if ( dep[Dep::CONFLICTS].size() > 0 )
00139 str << TAB << xml_tag_enclose(helixXML(dep[Dep::CONFLICTS]), "conflicts") << endl;
00140 if ( dep[Dep::OBSOLETES].size() > 0 )
00141 str << TAB << xml_tag_enclose(helixXML(dep[Dep::OBSOLETES]), "obsoletes") << endl;
00142 if ( dep[Dep::FRESHENS].size() > 0 )
00143 str << TAB << xml_tag_enclose(helixXML(dep[Dep::FRESHENS]), "freshens") << endl;
00144 if ( dep[Dep::REQUIRES].size() > 0 )
00145 str << TAB << xml_tag_enclose(helixXML(dep[Dep::REQUIRES]), "requires") << endl;
00146 if ( dep[Dep::RECOMMENDS].size() > 0 )
00147 str << TAB << xml_tag_enclose(helixXML(dep[Dep::RECOMMENDS]), "recommends") << endl;
00148 if ( dep[Dep::ENHANCES].size() > 0 )
00149 str << TAB << xml_tag_enclose(helixXML(dep[Dep::ENHANCES]), "enhances") << endl;
00150 if ( dep[Dep::SUPPLEMENTS].size() > 0 )
00151 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUPPLEMENTS]), "supplements") << endl;
00152 if ( dep[Dep::SUGGESTS].size() > 0 )
00153 str << TAB << xml_tag_enclose(helixXML(dep[Dep::SUGGESTS]), "suggests") << endl;
00154 return str.str();
00155 }
00156
00157 std::string helixXML( const Resolvable::constPtr &resolvable )
00158 {
00159 stringstream str;
00160 str << "<" << toLower (resolvable->kind().asString()) << ">" << endl;
00161 str << TAB << xml_tag_enclose (resolvable->name(), "name", true) << endl;
00162 if ( isKind<Package>(resolvable) ) {
00163 str << TAB << "<history>" << endl << TAB << "<update>" << endl;
00164 str << TAB2 << helixXML (resolvable->arch()) << endl;
00165 str << TAB2 << helixXML (resolvable->edition()) << endl;
00166 str << TAB << "</update>" << endl << TAB << "</history>" << endl;
00167 } else {
00168 str << TAB << helixXML (resolvable->arch()) << endl;
00169 str << TAB << helixXML (resolvable->edition()) << endl;
00170 }
00171 str << helixXML (resolvable->deps());
00172
00173 str << "</" << toLower (resolvable->kind().asString()) << ">" << endl;
00174 return str.str();
00175 }
00176
00177
00178
00179 Testcase::Testcase()
00180 :dumpPath("/var/log/YaST2/solverTestcase")
00181 {
00182 }
00183
00184 Testcase::Testcase(const std::string & path)
00185 :dumpPath(path)
00186 {
00187 }
00188
00189
00190 Testcase::~Testcase()
00191 {
00192 }
00193
00194 bool Testcase::createTestcase(Resolver & resolver)
00195 {
00196 PathInfo path (dumpPath);
00197
00198 if ( !path.isExist() ) {
00199 if (zypp::filesystem::mkdir (dumpPath)!=0) {
00200 ERR << "Cannot create directory " << dumpPath << endl;
00201 return false;
00202 }
00203 } else {
00204 if (!path.isDir()) {
00205 ERR << dumpPath << " is not a directory." << endl;
00206 return false;
00207 }
00208
00209 zypp::filesystem::clean_dir (dumpPath);
00210 }
00211
00212 zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" );
00213 zypp::base::LogControl::TmpExcessive excessive;
00214
00215 resolver.resolvePool();
00216
00217 zypp::base::LogControl::instance().logfile( "/var/log/YaST2/y2log" );
00218
00219 ResPool pool = resolver.pool();
00220 SourceTable sourceTable;
00221 PoolItemList items_to_install;
00222 PoolItemList items_to_remove;
00223 HelixResolvable system (dumpPath + "/solver-system.xml");
00224
00225 for ( ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it )
00226 {
00227 Resolvable::constPtr res = it->resolvable();
00228
00229 if ( it->status().isInstalled() ) {
00230
00231 system.addResolvable (res);
00232 } else {
00233
00234 ResObject::constPtr sourceItem = it->resolvable();
00235 Source_Ref source = sourceItem->source();
00236 if (sourceTable.find (source) == sourceTable.end()) {
00237 sourceTable[source] = new HelixResolvable(dumpPath + "/"
00238 + numstring(source.numericId())
00239 + "-package.xml");
00240 }
00241 sourceTable[source]->addResolvable (res);
00242 }
00243
00244 if ( it->status().isToBeInstalled()
00245 && !(it->status().isBySolver())) {
00246 items_to_install.push_back (*it);
00247 }
00248 if ( it->status().isToBeUninstalled()
00249 && !(it->status().isBySolver())) {
00250 items_to_remove.push_back (*it);
00251 }
00252 }
00253
00254
00255
00256 HelixControl control (dumpPath + "/solver-test.xml",
00257 sourceTable,
00258 resolver.architecture());
00259
00260 for (PoolItemList::const_iterator iter = items_to_install.begin(); iter != items_to_install.end(); iter++) {
00261 control.installResolvable (iter->resolvable());
00262 }
00263
00264 for (PoolItemList::const_iterator iter = items_to_remove.begin(); iter != items_to_remove.end(); iter++) {
00265 control.deleteResolvable (iter->resolvable());
00266 }
00267
00268 return true;
00269 }
00270
00271
00272
00273 HelixResolvable::HelixResolvable(const std::string & path)
00274 :dumpFile (path)
00275 {
00276 file = new ofstream(path.c_str());
00277 if (!file) {
00278 ZYPP_THROW (Exception( "Can't open " + path ) );
00279 }
00280
00281 *file << "<channel><subchannel>" << endl;
00282 }
00283
00284 HelixResolvable::~HelixResolvable()
00285 {
00286 *file << "</subchannel></channel>" << endl;
00287 }
00288
00289
00290 void HelixResolvable::addResolvable(const Resolvable::constPtr &resolvable)
00291 {
00292 *file << helixXML (resolvable);
00293 }
00294
00295
00296
00297 HelixControl::HelixControl(const std::string & controlPath,
00298 const SourceTable & sourceTable,
00299 const Arch & systemArchitecture,
00300 const std::string & systemPath)
00301 :dumpFile (controlPath)
00302 {
00303 file = new ofstream(controlPath.c_str());
00304 if (!file) {
00305 ZYPP_THROW (Exception( "Can't open " + controlPath ) );
00306 }
00307
00308 *file << "<?xml version=\"1.0\"?>" << endl
00309 << "<!-- testcase generated by YaST -->" << endl
00310 << "<test>" << endl
00311 << "<setup arch=\"" << systemArchitecture << "\">" << endl
00312 << TAB << "<system file=\"" << systemPath << "\"/>" << endl;
00313 for ( SourceTable::const_iterator it = sourceTable.begin();
00314 it != sourceTable.end(); ++it ) {
00315 Source_Ref source = it->first;
00316 *file << TAB << "<channel file=\"" << numstring(source.numericId())
00317 << "-package.xml\" name=\"" << numstring(source.numericId())
00318 << "\" />" << endl;
00319 }
00320 *file << "</setup>" << endl
00321 << "<trial>" << endl
00322 << "<showpool all=\"yes\"/>" << endl
00323 << "<establish/>" << endl
00324 << "<showpool all=\"true\" prefix=\">!> ESTABLISHED:\"/>" << endl;
00325 }
00326
00327 HelixControl::HelixControl()
00328 :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
00329 {
00330 HelixControl (dumpFile);
00331 }
00332
00333 HelixControl::~HelixControl()
00334 {
00335 *file << "</trial>" << endl
00336 << "</test>" << endl;
00337 }
00338
00339 void HelixControl::installResolvable(const ResObject::constPtr &resObject)
00340 {
00341 Source_Ref source = resObject->source();
00342 *file << "<install channel=\"" << numstring(source.numericId()) << "\" kind=\"" << toLower (resObject->kind().asString()) << "\""
00343 << " name=\"" << resObject->name() << "\"" << "/>" << endl;
00344 }
00345
00346 void HelixControl::deleteResolvable(const ResObject::constPtr &resObject)
00347 {
00348 Source_Ref source = resObject->source();
00349 *file << "<uninstall " << " kind=\"" << toLower (resObject->kind().asString()) << "\""
00350 << " name=\"" << resObject->name() << "\"" << "/>" << endl;
00351 }
00352
00353
00355 };
00358 };
00361 };