16#include <boost/iterator/function_output_iterator.hpp>
18#define ZYPP_USE_RESOLVER_INTERNALS
24#include <zypp-core/base/GzStream>
42#include <yaml-cpp/yaml.h>
45#include <solv/testcase.h>
63 :
dumpPath(
"/var/log/YaST2/solverTestcase")
66 Testcase::Testcase(std::string path)
73 bool Testcase::createTestcase(Resolver & resolver,
bool dumpPool,
bool runSolver)
76 if ( not resolver.get() ) {
77 WAR <<
"Can't createTestcase if the satsolver is not yet initialized." << endl;
81 MIL <<
"createTestcase at " <<
dumpPath << (dumpPool?
" dumpPool":
"") << (runSolver?
" runSolver":
"") << endl;
82 PathInfo path (dumpPath);
84 if ( !path.isExist() ) {
86 ERR <<
"Cannot create directory " <<
dumpPath << endl;
104 resolver.resolvePool();
107 ResPool pool = resolver.pool();
108 PoolItemList items_to_install;
109 PoolItemList items_to_remove;
110 PoolItemList items_locked;
111 PoolItemList items_keep;
114 const std::string slvTestcaseName =
"testcase.t";
115 const std::string slvResult =
"solver.result";
118 [ nrepos = resolver.get()->pool->nrepos ](
auto **x ){
120 for ( int i = 1; i < nrepos; i++ )
121 solv_free((void *)x[i]);
122 solv_free((void *)x);
125 if ( ::testcase_write( resolver.get(),
dumpPath.c_str(), TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS, slvTestcaseName.c_str(), slvResult.c_str() ) == 0 ) {
126 ERR <<
"Failed to write solv data, aborting." << endl;
131 const sat::Pool & satpool( sat::Pool::instance() );
135 const auto addTag = [&](
const std::string & tag_r,
bool yesno_r = true ){
136 yOut << YAML::Key << tag_r << YAML::Value << yesno_r;
139 yOut << YAML::BeginMap << YAML::Key <<
"version" << YAML::Value <<
"1.0";
141 yOut << YAML::Key <<
"setup" << YAML::Value << YAML::BeginMap;
143 yOut << YAML::Key <<
"channels";
144 yOut << YAML::Value << YAML::BeginSeq;
146 std::set<Repository::IdType> repos;
147 for (
const PoolItem & pi : pool ) {
148 if ( pi.status().isToBeInstalled()
149 && !(pi.status().isBySolver())) {
150 items_to_install.push_back( pi );
152 if ( pi.status().isKept()
153 && !(pi.status().isBySolver())) {
154 items_keep.push_back( pi );
156 if ( pi.status().isToBeUninstalled()
157 && !(pi.status().isBySolver())) {
158 items_to_remove.push_back( pi );
160 if ( pi.status().isLocked()
161 && !(pi.status().isBySolver())) {
162 items_locked.push_back( pi );
165 const auto &myRepo = pi.repository();
166 const auto &myRepoInfo = myRepo.info();
167 if ( repos.find( myRepo.id()) == repos.end() ) {
168 repos.insert( myRepo.id() );
169 yOut << YAML::Value << YAML::BeginMap;
170 yOut << YAML::Key <<
"alias" << YAML::Value << myRepo.alias();
171 yOut << YAML::Key <<
"url" << YAML::BeginSeq;
172 for (
const auto &origin : myRepoInfo.repoOrigins () ) {
173 for (
const auto &originEndpoint : origin ) {
174 yOut << YAML::Value << originEndpoint.url().asString();
177 yOut << YAML::EndSeq;
178 yOut << YAML::Key <<
"path" << YAML::Value << myRepoInfo.path().asString();
179 yOut << YAML::Key <<
"type" << YAML::Value << myRepoInfo.type().asString();
180 yOut << YAML::Key <<
"generated" << YAML::Value << myRepo.generatedTimestamp().form(
"%Y-%m-%d %H:%M:%S" );
181 yOut << YAML::Key <<
"outdated" << YAML::Value << myRepo.suggestedExpirationTimestamp().form(
"%Y-%m-%d %H:%M:%S" );
182 yOut << YAML::Key <<
"priority" << YAML::Value << myRepoInfo.priority();
183 yOut << YAML::Key <<
"file" << YAML::Value << str::Format(
"%1%.repo.gz") % repoFileNames[myRepo.id()->repoid];
185 yOut << YAML::EndMap;
190 yOut << YAML::EndSeq;
192 yOut << YAML::Key <<
"arch" << YAML::Value << ZConfig::instance().systemArchitecture().asString() ;
193 yOut << YAML::Key <<
"solverTestcase" << YAML::Value << slvTestcaseName ;
194 yOut << YAML::Key <<
"solverResult" << YAML::Value << slvResult ;
197 const LocaleSet & addedLocales( satpool.getAddedRequestedLocales() );
198 const LocaleSet & removedLocales( satpool.getRemovedRequestedLocales() );
199 const LocaleSet & requestedLocales( satpool.getRequestedLocales() );
201 yOut << YAML::Key <<
"locales" << YAML::Value << YAML::BeginSeq ;
202 for (
const Locale& l : requestedLocales ) {
203 yOut << YAML::Value << YAML::BeginMap;
204 yOut << YAML::Key <<
"fate" << YAML::Value << ( addedLocales.count(l) ?
"added" :
"" ) ;
205 yOut << YAML::Key <<
"name" << YAML::Value << l.asString() ;
206 yOut << YAML::EndMap;
209 for (
const Locale& l : removedLocales ) {
210 yOut << YAML::Value << YAML::BeginMap;
211 yOut << YAML::Key <<
"fate" << YAML::Value <<
"removed" ;
212 yOut << YAML::Key <<
"name" << YAML::Value << l.asString() ;
213 yOut << YAML::EndMap;
215 yOut << YAML::EndSeq;
218 yOut << YAML::Key <<
"vendors" << YAML::Value << YAML::BeginSeq ;
219 VendorAttr::instance().foreachVendorList( [&](
const VendorAttr::VendorList& vlist )->
bool {
220 if ( ! vlist.empty() ) {
221 yOut << YAML::Value << YAML::BeginSeq;
222 for(
const auto & v : vlist )
223 yOut << YAML::Value << v ;
224 yOut << YAML::EndSeq;
228 yOut << YAML::EndSeq;
231 const auto &writeListOrFile = [&](
const std::string &name,
const auto &list,
const auto &callback ) {
232 if ( list.size() > 10 ) {
233 const std::string fName = str::Format(
"zypp-%1%.yaml") % name;
234 yOut << YAML::Key << name << YAML::Value << fName;
236 YAML::Emitter yOutFile;
237 callback( yOutFile, list );
239 std::ofstream fout( dumpPath+
"/"+fName );
240 fout << yOutFile.c_str();
242 yOut << YAML::Key << name << YAML::Value ;
243 callback( yOut, list );
248 const auto &writeAutoInst = [] ( YAML::Emitter &out,
const auto &autoInstalledList ) {
249 out << YAML::BeginSeq;
250 for ( IdString::IdType n : autoInstalledList ) {
255 writeListOrFile(
"autoinst", satpool.autoInstalled(), writeAutoInst );
258 const auto &writeModalias = []( YAML::Emitter &out,
const auto &modAliasList ){
259 out << YAML::BeginSeq;
260 for (
const auto &modAlias : modAliasList ) {
261 out << YAML::Value << modAlias ;
265 writeListOrFile(
"modalias", target::Modalias::instance().modaliasList(), writeModalias );
268 const auto &writeMultiVersion = [] ( YAML::Emitter &out,
const auto &multiversionList ) {
269 out << YAML::BeginSeq;
270 for (
const auto &multiver : multiversionList ) {
271 out << YAML::Value << multiver ;
275 writeListOrFile(
"multiversion", ZConfig::instance().multiversionSpec(), writeMultiVersion );
278 yOut << YAML::Key <<
"resolverFlags" << YAML::Value << YAML::BeginMap;
279 yOut << YAML::Key <<
"focus" << YAML::Value <<
asString( resolver.focus() );
281 addTag(
"ignorealreadyrecommended", resolver.ignoreAlreadyRecommended() );
282 addTag(
"onlyRequires", resolver.onlyRequires() );
283 addTag(
"forceResolve", resolver.forceResolve() );
285 addTag(
"cleandepsOnRemove", resolver.cleandepsOnRemove() );
287 addTag(
"allowDowngrade", resolver.allowDowngrade() );
288 addTag(
"allowNameChange", resolver.allowNameChange() );
289 addTag(
"allowArchChange", resolver.allowArchChange() );
290 addTag(
"allowVendorChange", resolver.allowVendorChange() );
292 addTag(
"dupAllowDowngrade", resolver.dupAllowDowngrade() );
293 addTag(
"dupAllowNameChange", resolver.dupAllowNameChange() );
294 addTag(
"dupAllowArchChange", resolver.dupAllowArchChange() );
295 addTag(
"dupAllowVendorChange", resolver.dupAllowVendorChange() );
298 yOut << YAML::EndMap;
299 yOut << YAML::EndMap;
301 yOut << YAML::Key <<
"trials" << YAML::Value << YAML::BeginSeq;
303 yOut << YAML::Value << YAML::BeginMap << YAML::Key <<
"trial" << YAML::Value;
305 yOut << YAML::BeginSeq;
307 const auto &writeJobsToFile = [&](
const std::string &fName,
const auto &data,
const auto &cb ){
308 yOut << YAML::Value << YAML::BeginMap;
309 yOut << YAML::Key <<
"include" << YAML::Value << fName;
310 yOut << YAML::EndMap;
312 YAML::Emitter yOutFile;
313 yOutFile << YAML::BeginSeq;
314 cb( yOutFile, data );
315 yOutFile << YAML::EndSeq;
317 std::ofstream fout( dumpPath+
"/"+fName );
318 fout << yOutFile.c_str();
322 const auto &writePoolItemJobs = [](
const std::string &jobName ){
323 return [ &jobName ] ( YAML::Emitter &yOut,
const PoolItemList &poolItems,
bool shortInfo = false ) {
324 for (
const PoolItem & pi : poolItems ) {
325 yOut << YAML::Value << YAML::BeginMap;
327 std::stringstream status;
328 status << pi.status();
330 yOut << YAML::Key <<
"job" << YAML::Value << jobName
331 << YAML::Key <<
"kind" << YAML::Value << pi.kind().asString()
332 << YAML::Key <<
"name" << YAML::Value << pi.name()
333 << YAML::Key <<
"status" << YAML::Value << status.str();
335 yOut << YAML::Key <<
"channel" << YAML::Value << pi.repoInfo().alias()
336 << YAML::Key <<
"arch" << YAML::Value << pi.arch().asString()
337 << YAML::Key <<
"version" << YAML::Value << pi.edition().version()
338 << YAML::Key <<
"release" << YAML::Value << pi.edition().release();
340 yOut << YAML::EndMap;
345 const auto &writeMapJob = []( YAML::Emitter &yOut,
const std::string &name,
const std::map<std::string, std::string> &values = std::map<std::string, std::string>() ){
346 yOut << YAML::Value << YAML::BeginMap;
347 yOut << YAML::Key <<
"job" << YAML::Value << name;
348 for (
const auto &v : values )
349 yOut << YAML::Key << v.first << YAML::Value << v.second;
350 yOut << YAML::EndMap;
353 writePoolItemJobs(
"install")( yOut, items_to_install );
354 writePoolItemJobs(
"keep")( yOut, items_keep );
355 writePoolItemJobs(
"uninstall")( yOut, items_to_remove, true );
357 if ( items_locked.size() )
358 writeJobsToFile(
"zypp-locks.yaml", items_locked, writePoolItemJobs(
"lock") );
360 for (
const auto &v : resolver.extraRequires() )
361 writeMapJob( yOut,
"addRequire", { {
"name", v.asString() } } );
362 for (
const auto &v : SystemCheck::instance().requiredSystemCap() )
363 writeMapJob( yOut,
"addRequire", { {
"name", v.asString() } } );
365 for (
const auto &v : resolver.extraConflicts() )
366 writeMapJob( yOut,
"addConflict", { {
"name", v.asString() } } );
367 for (
const auto &v : SystemCheck::instance().conflictSystemCap() )
368 writeMapJob( yOut,
"addConflict", { {
"name", v.asString() } } );
370 for (
const auto &v : resolver.upgradeRepos() )
371 writeMapJob( yOut,
"upgradeRepo", { {
"name", v.alias() } } );
373 if ( resolver.isUpgradeMode() )
374 writeMapJob( yOut,
"distupgrade" );
376 if ( resolver.isUpdateMode() )
377 writeMapJob( yOut,
"update" );
379 if ( resolver.isVerifyingMode() )
380 writeMapJob( yOut,
"verify" );
382 yOut << YAML::EndSeq;
383 yOut << YAML::EndMap;
384 yOut << YAML::EndSeq;
385 yOut << YAML::EndMap;
386 yOut << YAML::EndMap;
388 std::ofstream fout( dumpPath+
"/zypp-control.yaml" );
389 fout << yOut.c_str();
391 MIL <<
"createTestcase done at " <<
dumpPath << endl;
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
std::string asString() const
Conversion to std::string
static LogControl instance()
Singleton access.
void logfile(const Pathname &logfile_r)
Set path for the logfile.
std::string asString(TInt val, char zero='0', char one='1')
For printing bits.
int clean_dir(const Pathname &path)
Like 'rm -r DIR/ *'.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
_dumpPath dumpPath(const Pathname &root_r, const Pathname &sub_r)
dumpPath iomaip to dump '(root_r)sub_r' output,
Easy-to use interface to the ZYPP dependency resolver.
Turn on excessive logging for the lifetime of this object.
Exchange LineWriter for the lifetime of this object.