[Aptitude-svn-commit] r3848 - in branches/aptitude-0.3/aptitude: .
src/generic/problemresolver
Daniel Burrows
dburrows at costa.debian.org
Mon Aug 15 20:25:44 UTC 2005
Author: dburrows
Date: Mon Aug 15 20:25:41 2005
New Revision: 3848
Added:
branches/aptitude-0.3/aptitude/src/generic/problemresolver/dummy_universe.cc
branches/aptitude-0.3/aptitude/src/generic/problemresolver/dummy_universe.h
Modified:
branches/aptitude-0.3/aptitude/ChangeLog
branches/aptitude-0.3/aptitude/src/generic/problemresolver/Makefile.am
branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc
Log:
Split out the dummy universe.
Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog (original)
+++ branches/aptitude-0.3/aptitude/ChangeLog Mon Aug 15 20:25:41 2005
@@ -1,5 +1,10 @@
2005-08-15 Daniel Burrows <dburrows at debian.org>
+ * src/generic/problemresolver/Makefile.am, src/generic/problemresolver/dummy_universe.cc, src/generic/problemresolver/dummy_universe.h, src/generic/problemresolver/test.cc:
+
+ Split the dummy universe out of the resolver test program so
+ that it can be used by other code.
+
* src/generic/Makefile.am:
Add exceptions.h to Makefile.am.
Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/Makefile.am (original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/Makefile.am Mon Aug 15 20:25:41 2005
@@ -4,4 +4,6 @@
noinst_PROGRAMS=test
-test_SOURCES=test.cc dump_universe.h exceptions.h problemresolver.h solution.h
+test_SOURCES=test.cc dump_universe.h \
+ dummy_universe.cc dummy_universe.h \
+ exceptions.h problemresolver.h solution.h
Added: branches/aptitude-0.3/aptitude/src/generic/problemresolver/dummy_universe.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/dummy_universe.cc Mon Aug 15 20:25:41 2005
@@ -0,0 +1,152 @@
+// dummy_universe.cc
+//
+// Copyright (C) 2005 Daniel Burrows
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+#include "dummy_universe.h"
+
+using namespace std;
+
+dummy_package::dummy_package(const string &_name, unsigned int id)
+ :name(_name), ID(id)
+{
+}
+
+dummy_package::~dummy_package()
+{
+ for(version_iterator i=versions.begin(); i!=versions.end(); ++i)
+ delete *i;
+}
+
+dummy_version *dummy_package::version_from_name(const string &the_name) const
+{
+ for(version_iterator i=versions.begin(); i!=versions.end(); ++i)
+ if((*i)->get_name()==the_name)
+ return *i;
+
+ throw NoSuchNameError("version of package "+name, the_name);
+}
+
+bool dummy_dep::broken() const
+{
+ if(source->get_package().current_version() != *source)
+ return false;
+
+ for(solver_iterator i=target_set.begin();
+ i!=target_set.end(); ++i)
+ if((*i)->get_package().current_version() == **i)
+ return false;
+
+ return true;
+}
+
+dummy_universe::~dummy_universe()
+{
+ for(vector<dummy_package *>::const_iterator i=packages.begin();
+ i!=packages.end(); ++i)
+ delete *i;
+
+ for(vector<dummy_dep *>::const_iterator i=deps.begin();
+ i!=deps.end(); ++i)
+ delete *i;
+}
+
+
+void dummy_universe::add_package(const string &name,
+ vector<string> the_versions,
+ const string &curname)
+{
+ assert(!the_versions.empty());
+
+ packages.push_back(new dummy_package(name, packages.size()));
+
+ for(vector<string>::const_iterator i=the_versions.begin();
+ i!=the_versions.end(); ++i)
+ {
+ versions.push_back(new dummy_version(*i, packages.back(), versions.size()));
+ packages.back()->add_version(versions.back());
+ }
+
+ packages.back()->set_current_version(packages.back()->version_from_name(curname));
+
+ packages_by_name[name]=packages.back();
+}
+
+void dummy_universe::add_dep(const string &pkg_name, const string &pkg_ver,
+ const vector<pair<string, string> > &target_names,
+ bool is_conflict, bool is_soft)
+{
+ dummy_package *pkg=find_package_internal(pkg_name);
+
+ set<dummy_version *, compare_dummy_versions> targets;
+ set<dummy_package *, compare_dummy_packages> packages;
+
+ for(vector<pair<string, string> >::const_iterator i=target_names.begin();
+ i!=target_names.end(); ++i)
+ {
+ dummy_package *pkg=find_package_internal(i->first);
+
+ packages.insert(pkg);
+ targets.insert(pkg->version_from_name(i->second));
+ }
+
+ if(!is_conflict)
+ deps.push_back(new dummy_dep(pkg->version_from_name(pkg_ver),
+ vector<dummy_version *>(targets.begin(), targets.end()),
+ deps.size(),
+ is_soft));
+ else
+ {
+ set<dummy_version *> targets2;
+
+ for(set<dummy_package *>::const_iterator i=packages.begin();
+ i!=packages.end(); ++i)
+ for(dummy_package::version_iterator j=(*i)->versions_begin();
+ j!=(*i)->versions_end(); ++j)
+ if(targets.find(*j)==targets.end())
+ targets2.insert(*j);
+
+ deps.push_back(new dummy_dep(pkg->version_from_name(pkg_ver),
+ vector<dummy_version *>(targets2.begin(), targets2.end()),
+ deps.size(),
+ is_soft));
+ }
+
+ dummy_dep *newdep=deps.back();
+
+ newdep->get_source().add_dep(newdep);
+
+ for(dummy_dep::solver_iterator i=newdep->solvers_begin();
+ i!=newdep->solvers_end(); ++i)
+ (*i)->add_revdep(newdep);
+}
+
+
+ostream &operator<<(ostream &out, const dummy_universe::dep &d)
+{
+ out << d.get_source().get_package().get_name() << " " << d.get_source().get_name() << " -> {";
+ for(dummy_universe::dep::solver_iterator i=d.solvers_begin();
+ !i.end(); ++i)
+ {
+ if(i!=d.solvers_begin())
+ out << ", ";
+ out << (*i).get_package().get_name() << " " << (*i).get_name();
+ }
+ out << "}";
+
+ return out;
+}
Added: branches/aptitude-0.3/aptitude/src/generic/problemresolver/dummy_universe.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/dummy_universe.h Mon Aug 15 20:25:41 2005
@@ -0,0 +1,730 @@
+// dummy_universe.h -*-c++-*-
+//
+// Copyright (C) 2005 Daniel Burrows
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
+// A package dependency universe that's not terribly efficient, but
+// easy to set up for testing.
+
+#ifndef DUMMY_UNIVERSE_H
+#define DUMMY_UNIVERSE_H
+
+#include <iostream>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "../exception.h"
+
+// An error type that's thrown when a name lookup fails.
+class NoSuchNameError:public Exception
+{
+ std::string name;
+ std::string type;
+public:
+ NoSuchNameError(const std::string &_type, const std::string &_name)
+ :name(_name), type(_type) {}
+
+ std::string errmsg() const {return "No "+type+" named "+name;}
+};
+
+template<class T1, class T2>
+class wrap_ptr_iter
+{
+ typename std::vector<T1 *>::const_iterator realiter, realend;
+public:
+ wrap_ptr_iter(const std::vector<T1 *> &parent)
+ :realiter(parent.begin()), realend(parent.end())
+ {
+ }
+
+ wrap_ptr_iter(const typename std::vector<T1 *>::const_iterator &begin,
+ const typename std::vector<T1 *>::const_iterator &end)
+ :realiter(begin), realend(end)
+ {
+ }
+
+ bool operator==(const wrap_ptr_iter &other) const
+ {
+ return realiter==other.realiter;
+ }
+
+ bool operator!=(const wrap_ptr_iter &other) const
+ {
+ return realiter!=other.realiter;
+ }
+
+ bool end() const
+ {
+ return realiter == realend;
+ }
+
+ wrap_ptr_iter &operator++()
+ {
+ ++realiter;
+ return *this;
+ }
+
+ const T2 operator*() const
+ {
+ return T2(*realiter);
+ }
+};
+
+class dummy_universe;
+class dummy_version;
+
+/** A dummy package type */
+class dummy_package
+{
+ /** The name of the package is not used by the generic algorithm,
+ * but is used as helpful output from the test cases.
+ */
+ std::string name;
+
+ /** The versions of this package. The first entry in this list is
+ * the current version.
+ */
+ std::vector<dummy_version *> versions;
+
+ /** The current version of this package; defaults to the first
+ * element of "versions".
+ */
+ dummy_version *cur;
+
+ /** The ID of this version. */
+ unsigned int ID;
+
+ dummy_package(const dummy_package &other);
+public:
+ typedef std::vector<dummy_version *>::const_iterator version_iterator;
+
+ /** Creates a dummy package. */
+ dummy_package(const std::string &_name, unsigned int id);
+
+ virtual ~dummy_package();
+
+ std::string get_name() const {return name;}
+ unsigned int get_id() const {return ID;}
+
+ /** Dummy packages are equivalent iff they are the same object. */
+ bool operator==(const dummy_package &other) const
+ {
+ return this == &other;
+ }
+
+ bool operator!=(const dummy_package &other) const
+ {
+ return this != &other;
+ }
+
+ bool operator<(const dummy_package &other) const
+ {
+ return ID < other.ID;
+ }
+
+ void add_version(dummy_version *version)
+ {
+ if(versions.empty())
+ cur=version;
+ versions.push_back(version);
+ }
+
+ const dummy_version ¤t_version() const {return *cur;}
+ version_iterator versions_begin() const {return versions.begin();}
+ version_iterator versions_end() const {return versions.end();}
+
+ /** Returns the version corresponding to the given name or aborts */
+ dummy_version *version_from_name(const std::string &the_name) const;
+
+ /** Sets the current version to the given version. */
+ void set_current_version(dummy_version *v)
+ {
+ cur=v;
+ }
+};
+
+class dummy_dep;
+
+/** A dummy version type */
+class dummy_version
+{
+ std::string name;
+
+ const dummy_package *package;
+
+ std::vector<dummy_dep *> revdeps;
+ std::vector<dummy_dep *> deps;
+
+ /** The numerical ID of this version. */
+ int ID;
+
+ dummy_version(const dummy_version &other);
+public:
+ typedef std::vector<dummy_dep *>::const_iterator revdep_iterator;
+ typedef std::vector<dummy_dep *>::const_iterator dep_iterator;
+
+ dummy_version(const std::string &_name, const dummy_package *_package,
+ unsigned int id)
+ :name(_name), package(_package), ID(id)
+ {
+ }
+
+ std::string get_name() const {return name;}
+ unsigned int get_id() const {return ID;}
+
+ bool operator==(const dummy_version &other) const
+ {
+ return this == &other;
+ }
+
+ bool operator!=(const dummy_version &other) const
+ {
+ return this != &other;
+ }
+
+ bool operator<(const dummy_version &other) const
+ {
+ return ID < other.ID;
+ }
+
+ void add_revdep(dummy_dep *dep)
+ {
+ revdeps.push_back(dep);
+ }
+
+ void add_dep(dummy_dep *dep)
+ {
+ deps.push_back(dep);
+ }
+
+ const dummy_package &get_package() const {return *package;}
+
+ revdep_iterator revdeps_begin() const {return revdeps.begin();}
+ revdep_iterator revdeps_end() const {return revdeps.end();}
+
+ dep_iterator deps_begin() const {return deps.begin();}
+ dep_iterator deps_end() const {return deps.end();}
+};
+
+/** Indicates that either package_1 depends upon package_2 or
+ * package_1 conflicts with package_2.
+ */
+class dummy_dep
+{
+ dummy_version *source;
+ std::vector<dummy_version *> target_set;
+
+ dummy_dep(const dummy_dep &other);
+
+ unsigned int ID;
+
+ bool soft;
+public:
+ typedef std::vector<dummy_version *>::const_iterator solver_iterator;
+
+ dummy_dep(dummy_version *_source,
+ const std::vector<dummy_version *> &_target_set,
+ unsigned int _ID, bool _soft)
+ :source(_source), target_set(_target_set), ID(_ID), soft(_soft)
+ {
+ }
+
+ bool is_soft() const
+ {
+ return soft;
+ }
+
+ bool operator==(const dummy_dep &other) const
+ {
+ return this==&other;
+ }
+
+ bool operator!=(const dummy_dep &other) const
+ {
+ return this!=&other;
+ }
+
+ bool operator<(const dummy_dep &other) const
+ {
+ return ID<other.ID;
+ }
+
+ dummy_version &get_source() const {return *source;}
+
+ solver_iterator solvers_begin() const
+ {
+ return target_set.begin();
+ }
+
+ solver_iterator solvers_end() const
+ {
+ return target_set.end();
+ }
+
+ /** Not part of the generic interface (although it could be);
+ * returns \b true if the dep is not satisfied in the global
+ * state (i.e., ignores any solution computation in progress).
+ */
+ bool broken() const;
+};
+
+/** Represents the world of all packages and dependencies. */
+class dummy_universe
+{
+public:
+ class version;
+ class dep;
+
+ class package
+ {
+ const dummy_package *real_package;
+ public:
+ package():real_package(0) {}
+ package(const dummy_package *_real_package)
+ :real_package(_real_package)
+ {
+ }
+
+ typedef wrap_ptr_iter<dummy_version, version> version_iterator;
+
+ bool operator==(const package &other) const
+ {
+ return real_package==other.real_package;
+ }
+
+ bool operator!=(const package &other) const
+ {
+ return real_package!=other.real_package;
+ }
+
+ bool operator<(const package &other) const
+ {
+ return (*real_package)<(*other.real_package);
+ }
+
+ std::string get_name() const
+ {
+ return real_package->get_name();
+ }
+
+ unsigned int get_id() const
+ {
+ return real_package->get_id();
+ }
+
+ version current_version() const
+ {
+ return version(&real_package->current_version());
+ }
+
+ version version_from_name(const std::string &name) const
+ {
+ return version(real_package->version_from_name(name));
+ }
+
+ wrap_ptr_iter<dummy_version, version> versions_begin() const
+ {
+ return wrap_ptr_iter<dummy_version, version>(real_package->versions_begin(), real_package->versions_end());
+ }
+ };
+
+ class version
+ {
+ const dummy_version *real_version;
+ public:
+ typedef wrap_ptr_iter<dummy_dep, dep> revdep_iterator;
+ typedef wrap_ptr_iter<dummy_dep, dep> dep_iterator;
+
+ version():real_version(0) {}
+ version(const dummy_version *_real_version)
+ :real_version(_real_version)
+ {
+ }
+
+ bool operator==(const version &other) const
+ {
+ return real_version==other.real_version;
+ }
+
+ bool operator!=(const version &other) const
+ {
+ return real_version!=other.real_version;
+ }
+
+ bool operator<(const version &other) const
+ {
+ return (*real_version)<(*other.real_version);
+ }
+
+ package get_package() const
+ {
+ return package(&real_version->get_package());
+ }
+
+ std::string get_name() const
+ {
+ return real_version->get_name();
+ }
+
+ unsigned int get_id() const
+ {
+ return real_version->get_id();
+ }
+
+ wrap_ptr_iter<dummy_dep, dep> revdeps_begin() const
+ {
+ return wrap_ptr_iter<dummy_dep, dep>(real_version->revdeps_begin(),
+ real_version->revdeps_end());
+ }
+
+ wrap_ptr_iter<dummy_dep, dep> deps_begin() const
+ {
+ return wrap_ptr_iter<dummy_dep, dep>(real_version->deps_begin(),
+ real_version->deps_end());
+ }
+ };
+
+
+ class dep
+ {
+ const dummy_dep *real_dep;
+ public:
+ dep():real_dep(0) {}
+ dep(const dummy_dep *_real_dep)
+ :real_dep(_real_dep)
+ {
+ }
+ dep(const dep &other)
+ :real_dep(other.real_dep)
+ {
+ }
+
+ typedef wrap_ptr_iter<dummy_version, version> solver_iterator;
+
+ bool is_soft() const
+ {
+ return real_dep->is_soft();
+ }
+
+ bool operator==(const dep &other) const
+ {
+ return real_dep==other.real_dep;
+ }
+
+ bool operator!=(const dep &other) const
+ {
+ return real_dep!=other.real_dep;
+ }
+
+ bool operator<(const dep &other) const
+ {
+ return (*real_dep)<(*other.real_dep);
+ }
+
+ version get_source() const
+ {
+ return version(&real_dep->get_source());
+ }
+
+ wrap_ptr_iter<dummy_version, version> solvers_begin() const
+ {
+ return wrap_ptr_iter<dummy_version, version>(real_dep->solvers_begin(),
+ real_dep->solvers_end());
+ }
+
+ template<class Sol>
+ bool broken_under(const Sol& s) const
+ {
+ if(s.version_of(get_source().get_package()) != get_source())
+ return false;
+
+ for(dummy_dep::solver_iterator i=real_dep->solvers_begin();
+ i!=real_dep->solvers_end(); ++i)
+ if(s.version_of(version(*i).get_package()) == version(*i))
+ return false;
+
+ return true;
+ }
+ };
+
+
+ typedef wrap_ptr_iter<dummy_package, package> package_iterator;
+ typedef wrap_ptr_iter<dummy_dep, dep> dep_iterator;
+
+ /** Finds broken dependencies. */
+ class broken_dep_iterator
+ {
+ std::vector<dummy_dep *>::const_iterator realiter;
+ std::vector<dummy_dep *>::const_iterator realend;
+ public:
+ broken_dep_iterator(const std::vector<dummy_dep *>::const_iterator &_realiter,
+ const std::vector<dummy_dep *>::const_iterator &_realend)
+ :realiter(_realiter), realend(_realend)
+ {
+ while(realiter!=realend && !(*realiter)->broken())
+ ++realiter;
+ }
+
+ bool operator==(const broken_dep_iterator &other) const
+ {
+ return realiter==other.realiter;
+ }
+
+ bool operator!=(const broken_dep_iterator &other) const
+ {
+ return realiter!=other.realiter;
+ }
+
+ bool end() const
+ {
+ return realiter == realend;
+ }
+
+ const dep operator*() const
+ {
+ assert(realiter!=realend);
+ return *realiter;
+ }
+
+ broken_dep_iterator &operator++()
+ {
+ if(realiter!=realend)
+ ++realiter;
+
+ while(realiter!=realend && !(*realiter)->broken())
+ ++realiter;
+
+ return *this;
+ }
+ };
+
+private:
+ /** All the packages in the universe. */
+ std::vector<dummy_package *> packages;
+ /** All the dependencies in the universe. */
+ std::vector<dummy_dep *> deps;
+ /** All the versions in the universe. */
+ std::vector<dummy_version *> versions;
+
+ /** Indexes packages by name. */
+ std::map<std::string, dummy_package *> packages_by_name;
+
+ struct compare_dummy_packages
+ {
+ bool operator()(dummy_package *p1, dummy_package *p2)
+ {
+ return p1->get_id() < p2->get_id();
+ }
+ };
+
+ struct compare_dummy_versions
+ {
+ bool operator()(dummy_version *v1, dummy_version *v2)
+ {
+ return v1->get_id() < v2->get_id();
+ }
+ };
+
+ dummy_package *find_package_internal(const std::string &pkg_name)
+ {
+ std::map<std::string, dummy_package *>::const_iterator pfound=packages_by_name.find(pkg_name);
+
+ if(pfound==packages_by_name.end())
+ throw NoSuchNameError("package", pkg_name);
+
+ return pfound->second;
+ }
+
+public:
+ virtual ~dummy_universe();
+
+ /** Lo, and it was a void, without form. */
+ dummy_universe() {}
+
+ /** Add a package to the universe.
+ *
+ * \param name the name of the new package.
+ * \param the_versions the names of the versions of that package.
+ * The first element of the list is the current version.
+ */
+ void add_package(const std::string &name,
+ std::vector<std::string> the_versions,
+ const std::string &curname);
+
+ /** Find a package by name. */
+ package find_package(const std::string &pkg_name)
+ {
+ return find_package_internal(pkg_name);
+ }
+
+ /** Add a dependency to the universe. For convenience
+ * this is std::string-based.
+ */
+ void add_dep(const std::string &pkg_name, const std::string &pkg_ver,
+ const std::vector<std::pair<std::string, std::string> > &target_names,
+ bool is_conflict, bool is_soft);
+
+ std::vector<package>::size_type get_package_count() const
+ {
+ return packages.size();
+ }
+
+ std::vector<version>::size_type get_version_count() const
+ {
+ return versions.size();
+ }
+
+ package_iterator packages_begin() const
+ {
+ return packages;
+ }
+
+ dep_iterator deps_begin() const
+ {
+ return deps;
+ }
+
+ broken_dep_iterator broken_begin() const
+ {
+ return broken_dep_iterator(deps.begin(), deps.end());
+ }
+};
+
+// A refcounting wrapper for a dummy_universe; used to sanitize memory
+// management without copying all over (and because the resolver
+// expects to be able to have a full copy of its argument type)
+class dummy_universe_ref
+{
+ struct _rep
+ {
+ int refcount;
+ dummy_universe *universe;
+
+ /** Start with 1 ref since our creator holds a ref. */
+ _rep(dummy_universe *_universe)
+ :refcount(1), universe(_universe)
+ {
+ }
+
+ void incref() {++refcount;}
+ void decref() {--refcount; if(refcount==0) delete this;}
+ };
+
+ _rep *rep;
+public:
+ typedef dummy_universe::package package;
+ typedef dummy_universe::version version;
+ typedef dummy_universe::dep dep;
+ typedef dummy_universe::package_iterator package_iterator;
+ typedef dummy_universe::dep_iterator dep_iterator;
+ typedef dummy_universe::broken_dep_iterator broken_dep_iterator;
+
+ dummy_universe_ref()
+ :rep(NULL)
+ {
+ }
+
+ dummy_universe_ref(const dummy_universe_ref &other)
+ :rep(other.rep)
+ {
+ if(rep)
+ rep->incref();
+ }
+
+ /** Assumes this is the first reference to the universe. */
+ dummy_universe_ref(dummy_universe *universe)
+ :rep(new _rep(universe))
+ {
+ }
+
+ ~dummy_universe_ref()
+ {
+ if(rep)
+ rep->decref();
+ }
+
+ dummy_universe_ref &operator=(const dummy_universe_ref &other)
+ {
+ if(other.rep)
+ other.rep->incref();
+ if(rep)
+ rep->decref();
+ rep=other.rep;
+
+ return *this;
+ }
+
+ operator void*() const
+ {
+ return (void *) (rep && rep->universe);
+ }
+
+ void add_package(const std::string &name,
+ std::vector<std::string> the_versions,
+ const std::string &curname) const
+ {
+ rep->universe->add_package(name, the_versions, curname);
+ }
+
+ void add_dep(std::string pkg_name, std::string pkg_ver,
+ const std::vector<std::pair<std::string, std::string> > &target_names,
+ bool is_conflict, bool is_soft)
+ {
+ rep->universe->add_dep(pkg_name, pkg_ver,
+ target_names, is_conflict, is_soft);
+ }
+
+ package find_package(const std::string &pkg_name) const
+ {
+ return rep->universe->find_package(pkg_name);
+ }
+
+ std::vector<package>::size_type get_package_count() const
+ {
+ return rep->universe->get_package_count();
+ }
+
+ std::vector<version>::size_type get_version_count() const
+ {
+ return rep->universe->get_version_count();
+ }
+
+ package_iterator packages_begin() const
+ {
+ return rep->universe->packages_begin();
+ }
+
+ dep_iterator deps_begin() const
+ {
+ return rep->universe->deps_begin();
+ }
+
+ broken_dep_iterator broken_begin() const
+ {
+ return rep->universe->broken_begin();
+ }
+};
+
+template<class T>
+class generic_problem_resolver;
+typedef generic_problem_resolver<dummy_universe_ref> dummy_resolver;
+
+std::ostream &operator<<(std::ostream &out, const dummy_universe::dep &d);
+
+#endif // DUMMY_UNIVERSE_H
Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc (original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc Mon Aug 15 20:25:41 2005
@@ -21,6 +21,7 @@
// in order to keep the APT end of things reasonably thin and
// efficient.
+#include "dummy_universe.h"
#include "problemresolver.h"
#include <iostream>
@@ -33,820 +34,6 @@
using namespace std;
-class Exception
-{
-public:
- virtual string errmsg() const=0;
- virtual ~Exception() {}
-};
-
-class NoSuchNameError:public Exception
-{
- string name;
- string type;
-public:
- NoSuchNameError(string _type, string _name)
- :name(_name), type(_type) {}
-
- string errmsg() const {return "No "+type+" named "+name;}
-};
-
-template<class T1, class T2>
-class wrap_ptr_iter
-{
- typename vector<T1 *>::const_iterator realiter, realend;
-public:
- wrap_ptr_iter(const vector<T1 *> &parent)
- :realiter(parent.begin()), realend(parent.end())
- {
- }
-
- wrap_ptr_iter(const typename vector<T1 *>::const_iterator &begin,
- const typename vector<T1 *>::const_iterator &end)
- :realiter(begin), realend(end)
- {
- }
-
- bool operator==(const wrap_ptr_iter &other) const
- {
- return realiter==other.realiter;
- }
-
- bool operator!=(const wrap_ptr_iter &other) const
- {
- return realiter!=other.realiter;
- }
-
- bool end() const
- {
- return realiter == realend;
- }
-
- wrap_ptr_iter &operator++()
- {
- ++realiter;
- return *this;
- }
-
- const T2 operator*() const
- {
- return T2(*realiter);
- }
-};
-
-class dummy_universe;
-class dummy_version;
-
-/** A dummy package type */
-class dummy_package
-{
- /** The name of the package is not used by the generic algorithm,
- * but is used as helpful output from the test cases.
- */
- string name;
-
- /** The versions of this package. The first entry in this list is
- * the current version.
- */
- vector<dummy_version *> versions;
-
- /** The current version of this package; defaults to the first
- * element of "versions".
- */
- dummy_version *cur;
-
- /** The ID of this version. */
- unsigned int ID;
-
- dummy_package(const dummy_package &other);
-public:
- typedef vector<dummy_version *>::const_iterator version_iterator;
-
- /** Creates a dummy package. */
- dummy_package(string _name, unsigned int id);
-
- virtual ~dummy_package();
-
- string get_name() const {return name;}
- unsigned int get_id() const {return ID;}
-
- /** Dummy packages are equivalent iff they are the same object. */
- bool operator==(const dummy_package &other) const
- {
- return this == &other;
- }
-
- bool operator!=(const dummy_package &other) const
- {
- return this != &other;
- }
-
- bool operator<(const dummy_package &other) const
- {
- return ID < other.ID;
- }
-
- void add_version(dummy_version *version)
- {
- if(versions.empty())
- cur=version;
- versions.push_back(version);
- }
-
- const dummy_version ¤t_version() const {return *cur;}
- version_iterator versions_begin() const {return versions.begin();}
- version_iterator versions_end() const {return versions.end();}
-
- /** Returns the version corresponding to the given name or aborts */
- dummy_version *version_from_name(const string &the_name) const;
-
- /** Sets the current version to the given version. */
- void set_current_version(dummy_version *v)
- {
- cur=v;
- }
-};
-
-class dummy_dep;
-
-/** A dummy version type */
-class dummy_version
-{
- string name;
-
- const dummy_package *package;
-
- vector<dummy_dep *> revdeps;
- vector<dummy_dep *> deps;
-
- /** The numerical ID of this version. */
- int ID;
-
- dummy_version(const dummy_version &other);
-public:
- typedef vector<dummy_dep *>::const_iterator revdep_iterator;
- typedef vector<dummy_dep *>::const_iterator dep_iterator;
-
- dummy_version(string _name, const dummy_package *_package,
- unsigned int id)
- :name(_name), package(_package), ID(id)
- {
- }
-
- string get_name() const {return name;}
- unsigned int get_id() const {return ID;}
-
- bool operator==(const dummy_version &other) const
- {
- return this == &other;
- }
-
- bool operator!=(const dummy_version &other) const
- {
- return this != &other;
- }
-
- bool operator<(const dummy_version &other) const
- {
- return ID < other.ID;
- }
-
- void add_revdep(dummy_dep *dep)
- {
- revdeps.push_back(dep);
- }
-
- void add_dep(dummy_dep *dep)
- {
- deps.push_back(dep);
- }
-
- const dummy_package &get_package() const {return *package;}
-
- revdep_iterator revdeps_begin() const {return revdeps.begin();}
- revdep_iterator revdeps_end() const {return revdeps.end();}
-
- dep_iterator deps_begin() const {return deps.begin();}
- dep_iterator deps_end() const {return deps.end();}
-};
-
-dummy_package::dummy_package(string _name, unsigned int id)
- :name(_name), ID(id)
-{
-}
-
-dummy_package::~dummy_package()
-{
- for(version_iterator i=versions.begin(); i!=versions.end(); ++i)
- delete *i;
-}
-
-dummy_version *dummy_package::version_from_name(const string &the_name) const
-{
- for(version_iterator i=versions.begin(); i!=versions.end(); ++i)
- if((*i)->get_name()==the_name)
- return *i;
-
- throw NoSuchNameError("version of package "+name, the_name);
-}
-
-/** Indicates that either package_1 depends upon package_2 or
- * package_1 conflicts with package_2.
- */
-class dummy_dep
-{
- dummy_version *source;
- vector<dummy_version *> target_set;
-
- dummy_dep(const dummy_dep &other);
-
- unsigned int ID;
-
- bool soft;
-public:
- typedef vector<dummy_version *>::const_iterator solver_iterator;
-
- dummy_dep(dummy_version *_source,
- const vector<dummy_version *> &_target_set,
- unsigned int _ID, bool _soft)
- :source(_source), target_set(_target_set), ID(_ID), soft(_soft)
- {
- }
-
- bool is_soft() const
- {
- return soft;
- }
-
- bool operator==(const dummy_dep &other) const
- {
- return this==&other;
- }
-
- bool operator!=(const dummy_dep &other) const
- {
- return this!=&other;
- }
-
- bool operator<(const dummy_dep &other) const
- {
- return ID<other.ID;
- }
-
- dummy_version &get_source() const {return *source;}
-
- solver_iterator solvers_begin() const
- {
- return target_set.begin();
- }
-
- solver_iterator solvers_end() const
- {
- return target_set.end();
- }
-
- /** Not part of the generic interface (although it could be);
- * returns \b true if the dep is not satisfied in the global
- * state (i.e., ignores any solution computation in progress).
- */
- bool broken() const
- {
- if(source->get_package().current_version() != *source)
- return false;
-
- for(solver_iterator i=target_set.begin();
- i!=target_set.end(); ++i)
- if((*i)->get_package().current_version() == **i)
- return false;
-
- return true;
- }
-};
-
-/** Represents the world of all packages and dependencies. */
-class dummy_universe
-{
-public:
- class version;
- class dep;
-
- class package
- {
- const dummy_package *real_package;
- public:
- package():real_package(0) {}
- package(const dummy_package *_real_package)
- :real_package(_real_package)
- {
- }
-
- typedef wrap_ptr_iter<dummy_version, version> version_iterator;
-
- bool operator==(const package &other) const
- {
- return real_package==other.real_package;
- }
-
- bool operator!=(const package &other) const
- {
- return real_package!=other.real_package;
- }
-
- bool operator<(const package &other) const
- {
- return (*real_package)<(*other.real_package);
- }
-
- string get_name() const
- {
- return real_package->get_name();
- }
-
- unsigned int get_id() const
- {
- return real_package->get_id();
- }
-
- version current_version() const
- {
- return version(&real_package->current_version());
- }
-
- version version_from_name(string name) const
- {
- return version(real_package->version_from_name(name));
- }
-
- wrap_ptr_iter<dummy_version, version> versions_begin() const
- {
- return wrap_ptr_iter<dummy_version, version>(real_package->versions_begin(), real_package->versions_end());
- }
- };
-
- class version
- {
- const dummy_version *real_version;
- public:
- typedef wrap_ptr_iter<dummy_dep, dep> revdep_iterator;
- typedef wrap_ptr_iter<dummy_dep, dep> dep_iterator;
-
- version():real_version(0) {}
- version(const dummy_version *_real_version)
- :real_version(_real_version)
- {
- }
-
- bool operator==(const version &other) const
- {
- return real_version==other.real_version;
- }
-
- bool operator!=(const version &other) const
- {
- return real_version!=other.real_version;
- }
-
- bool operator<(const version &other) const
- {
- return (*real_version)<(*other.real_version);
- }
-
- package get_package() const
- {
- return package(&real_version->get_package());
- }
-
- string get_name() const
- {
- return real_version->get_name();
- }
-
- unsigned int get_id() const
- {
- return real_version->get_id();
- }
-
- wrap_ptr_iter<dummy_dep, dep> revdeps_begin() const
- {
- return wrap_ptr_iter<dummy_dep, dep>(real_version->revdeps_begin(),
- real_version->revdeps_end());
- }
-
- wrap_ptr_iter<dummy_dep, dep> deps_begin() const
- {
- return wrap_ptr_iter<dummy_dep, dep>(real_version->deps_begin(),
- real_version->deps_end());
- }
- };
-
-
- class dep
- {
- const dummy_dep *real_dep;
- public:
- dep():real_dep(0) {}
- dep(const dummy_dep *_real_dep)
- :real_dep(_real_dep)
- {
- }
- dep(const dep &other)
- :real_dep(other.real_dep)
- {
- }
-
- typedef wrap_ptr_iter<dummy_version, version> solver_iterator;
-
- bool is_soft() const
- {
- return real_dep->is_soft();
- }
-
- bool operator==(const dep &other) const
- {
- return real_dep==other.real_dep;
- }
-
- bool operator!=(const dep &other) const
- {
- return real_dep!=other.real_dep;
- }
-
- bool operator<(const dep &other) const
- {
- return (*real_dep)<(*other.real_dep);
- }
-
- version get_source() const
- {
- return version(&real_dep->get_source());
- }
-
- wrap_ptr_iter<dummy_version, version> solvers_begin() const
- {
- return wrap_ptr_iter<dummy_version, version>(real_dep->solvers_begin(),
- real_dep->solvers_end());
- }
-
- template<class Sol>
- bool broken_under(const Sol& s) const
- {
- if(s.version_of(get_source().get_package()) != get_source())
- return false;
-
- for(dummy_dep::solver_iterator i=real_dep->solvers_begin();
- i!=real_dep->solvers_end(); ++i)
- if(s.version_of(version(*i).get_package()) == version(*i))
- return false;
-
- return true;
- }
- };
-
-
- typedef wrap_ptr_iter<dummy_package, package> package_iterator;
- typedef wrap_ptr_iter<dummy_dep, dep> dep_iterator;
-
- /** Finds broken dependencies. */
- class broken_dep_iterator
- {
- vector<dummy_dep *>::const_iterator realiter;
- vector<dummy_dep *>::const_iterator realend;
- public:
- broken_dep_iterator(const vector<dummy_dep *>::const_iterator &_realiter,
- const vector<dummy_dep *>::const_iterator &_realend)
- :realiter(_realiter), realend(_realend)
- {
- while(realiter!=realend && !(*realiter)->broken())
- ++realiter;
- }
-
- bool operator==(const broken_dep_iterator &other) const
- {
- return realiter==other.realiter;
- }
-
- bool operator!=(const broken_dep_iterator &other) const
- {
- return realiter!=other.realiter;
- }
-
- bool end() const
- {
- return realiter == realend;
- }
-
- const dep operator*() const
- {
- assert(realiter!=realend);
- return *realiter;
- }
-
- broken_dep_iterator &operator++()
- {
- if(realiter!=realend)
- ++realiter;
-
- while(realiter!=realend && !(*realiter)->broken())
- ++realiter;
-
- return *this;
- }
- };
-
-private:
- /** All the packages in the universe. */
- vector<dummy_package *> packages;
- /** All the dependencies in the universe. */
- vector<dummy_dep *> deps;
- /** All the versions in the universe. */
- vector<dummy_version *> versions;
-
- /** Indexes packages by name. */
- map<string, dummy_package *> packages_by_name;
-
- struct compare_dummy_packages
- {
- bool operator()(dummy_package *p1, dummy_package *p2)
- {
- return p1->get_id() < p2->get_id();
- }
- };
-
- struct compare_dummy_versions
- {
- bool operator()(dummy_version *v1, dummy_version *v2)
- {
- return v1->get_id() < v2->get_id();
- }
- };
-
- dummy_package *find_package_internal(string pkg_name)
- {
- map<string, dummy_package *>::const_iterator pfound=packages_by_name.find(pkg_name);
-
- if(pfound==packages_by_name.end())
- throw NoSuchNameError("package", pkg_name);
-
- return pfound->second;
- }
-
-public:
- virtual ~dummy_universe()
- {
- for(vector<dummy_package *>::const_iterator i=packages.begin();
- i!=packages.end(); ++i)
- delete *i;
-
- for(vector<dummy_dep *>::const_iterator i=deps.begin();
- i!=deps.end(); ++i)
- delete *i;
- }
-
- /** Lo, and it was a void, without form. */
- dummy_universe() {}
-
- /** Add a package to the universe.
- *
- * \param name the name of the new package.
- * \param the_versions the names of the versions of that package.
- * The first element of the list is the current version.
- */
- void add_package(string name,
- vector<string> the_versions,
- string curname)
- {
- assert(!the_versions.empty());
-
- packages.push_back(new dummy_package(name, packages.size()));
-
- for(vector<string>::const_iterator i=the_versions.begin();
- i!=the_versions.end(); ++i)
- {
- versions.push_back(new dummy_version(*i, packages.back(), versions.size()));
- packages.back()->add_version(versions.back());
- }
-
- packages.back()->set_current_version(packages.back()->version_from_name(curname));
-
- packages_by_name[name]=packages.back();
- }
-
- /** Find a package by name. */
- package find_package(string pkg_name)
- {
- return find_package_internal(pkg_name);
- }
-
- /** Add a dependency to the universe. For convenience
- * this is string-based.
- */
- void add_dep(string pkg_name, string pkg_ver,
- const vector<pair<string, string> > &target_names,
- bool is_conflict, bool is_soft)
- {
- dummy_package *pkg=find_package_internal(pkg_name);
-
- set<dummy_version *, compare_dummy_versions> targets;
- set<dummy_package *, compare_dummy_packages> packages;
-
- for(vector<pair<string, string> >::const_iterator i=target_names.begin();
- i!=target_names.end(); ++i)
- {
- dummy_package *pkg=find_package_internal(i->first);
-
- packages.insert(pkg);
- targets.insert(pkg->version_from_name(i->second));
- }
-
- if(!is_conflict)
- deps.push_back(new dummy_dep(pkg->version_from_name(pkg_ver),
- vector<dummy_version *>(targets.begin(), targets.end()),
- deps.size(),
- is_soft));
- else
- {
- set<dummy_version *> targets2;
-
- for(set<dummy_package *>::const_iterator i=packages.begin();
- i!=packages.end(); ++i)
- for(dummy_package::version_iterator j=(*i)->versions_begin();
- j!=(*i)->versions_end(); ++j)
- if(targets.find(*j)==targets.end())
- targets2.insert(*j);
-
- deps.push_back(new dummy_dep(pkg->version_from_name(pkg_ver),
- vector<dummy_version *>(targets2.begin(), targets2.end()),
- deps.size(),
- is_soft));
- }
-
- dummy_dep *newdep=deps.back();
-
- newdep->get_source().add_dep(newdep);
-
- for(dummy_dep::solver_iterator i=newdep->solvers_begin();
- i!=newdep->solvers_end(); ++i)
- (*i)->add_revdep(newdep);
- }
-
- vector<package>::size_type get_package_count() const
- {
- return packages.size();
- }
-
- vector<version>::size_type get_version_count() const
- {
- return versions.size();
- }
-
- package_iterator packages_begin() const
- {
- return packages;
- }
-
- dep_iterator deps_begin() const
- {
- return deps;
- }
-
- broken_dep_iterator broken_begin() const
- {
- return broken_dep_iterator(deps.begin(), deps.end());
- }
-};
-
-// A refcounting wrapper for a dummy_universe; used to sanitize memory
-// management without copying all over (and because the resolver
-// expects to be able to have a full copy of its argument type)
-class dummy_universe_ref
-{
- struct _rep
- {
- int refcount;
- dummy_universe *universe;
-
- /** Start with 1 ref since our creator holds a ref. */
- _rep(dummy_universe *_universe)
- :refcount(1), universe(_universe)
- {
- }
-
- void incref() {++refcount;}
- void decref() {--refcount; if(refcount==0) delete this;}
- };
-
- _rep *rep;
-public:
- typedef dummy_universe::package package;
- typedef dummy_universe::version version;
- typedef dummy_universe::dep dep;
- typedef dummy_universe::package_iterator package_iterator;
- typedef dummy_universe::dep_iterator dep_iterator;
- typedef dummy_universe::broken_dep_iterator broken_dep_iterator;
-
- dummy_universe_ref()
- :rep(NULL)
- {
- }
-
- dummy_universe_ref(const dummy_universe_ref &other)
- :rep(other.rep)
- {
- if(rep)
- rep->incref();
- }
-
- /** Assumes this is the first reference to the universe. */
- dummy_universe_ref(dummy_universe *universe)
- :rep(new _rep(universe))
- {
- }
-
- ~dummy_universe_ref()
- {
- if(rep)
- rep->decref();
- }
-
- dummy_universe_ref &operator=(const dummy_universe_ref &other)
- {
- if(other.rep)
- other.rep->incref();
- if(rep)
- rep->decref();
- rep=other.rep;
-
- return *this;
- }
-
- operator void*() const
- {
- return (void *) (rep && rep->universe);
- }
-
- void add_package(string name,
- vector<string> the_versions,
- string curname) const
- {
- rep->universe->add_package(name, the_versions, curname);
- }
-
- void add_dep(string pkg_name, string pkg_ver,
- const vector<pair<string, string> > &target_names,
- bool is_conflict, bool is_soft)
- {
- rep->universe->add_dep(pkg_name, pkg_ver,
- target_names, is_conflict, is_soft);
- }
-
- package find_package(string pkg_name) const
- {
- return rep->universe->find_package(pkg_name);
- }
-
- vector<package>::size_type get_package_count() const
- {
- return rep->universe->get_package_count();
- }
-
- vector<version>::size_type get_version_count() const
- {
- return rep->universe->get_version_count();
- }
-
- package_iterator packages_begin() const
- {
- return rep->universe->packages_begin();
- }
-
- dep_iterator deps_begin() const
- {
- return rep->universe->deps_begin();
- }
-
- broken_dep_iterator broken_begin() const
- {
- return rep->universe->broken_begin();
- }
-};
-
-typedef generic_problem_resolver<dummy_universe_ref> dummy_resolver;
-
-ostream &operator<<(ostream &out, const dummy_resolver::dep &d)
-{
- out << d.get_source().get_package().get_name() << " " << d.get_source().get_name() << " -> {";
- for(dummy_resolver::dep::solver_iterator i=d.solvers_begin();
- !i.end(); ++i)
- {
- if(i!=d.solvers_begin())
- out << ", ";
- out << (*i).get_package().get_name() << " " << (*i).get_name();
- }
- out << "}";
-
- return out;
-}
-
// To make things easier, the tests are specified as plaintext files.
// The syntax is quite simple: it consists of whitespace-separated
// words, of the form:
@@ -870,7 +57,7 @@
{
string msg;
public:
- ParseError(string _msg):msg(_msg) {}
+ ParseError(const string &_msg):msg(_msg) {}
string errmsg() const {return msg;}
};
More information about the Aptitude-svn-commit
mailing list