aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-14 21:14:38 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-14 21:14:38 +0100
commite9674e5995244ffdda31e7ddb956330006b33d10 (patch)
tree123e10a6b935049b21f32642f76f6b6c445f23d3
parente9b158c79c03382410637ba42816692d1bae610d (diff)
downloadpaludis-e9674e5995244ffdda31e7ddb956330006b33d10.tar.gz
paludis-e9674e5995244ffdda31e7ddb956330006b33d10.tar.xz
More blocker work
-rw-r--r--.gitignore1
-rw-r--r--paludis/repositories/e/dep_parser.cc7
-rw-r--r--paludis/repositories/e/dep_parser.se3
-rw-r--r--paludis/repositories/e/eapis/2.conf2
-rw-r--r--paludis/repositories/e/eapis/exheres-0.conf2
-rw-r--r--paludis/repositories/e/eapis/paludis-1.conf2
-rw-r--r--paludis/repositories/fake/fake_installed_repository.cc13
-rw-r--r--paludis/repositories/fake/fake_installed_repository.hh5
-rw-r--r--paludis/resolver/Makefile.am24
-rw-r--r--paludis/resolver/resolver.cc46
-rw-r--r--paludis/resolver/resolver_TEST_blockers.cc98
-rwxr-xr-xpaludis/resolver/resolver_TEST_blockers_cleanup.sh9
-rwxr-xr-xpaludis/resolver/resolver_TEST_blockers_setup.sh45
-rw-r--r--paludis/resolver/resolver_TEST_suggestions.cc235
-rw-r--r--paludis/resolver/resolver_test.cc296
-rw-r--r--paludis/resolver/resolver_test.hh114
16 files changed, 642 insertions, 260 deletions
diff --git a/.gitignore b/.gitignore
index 9bbcb55..71010b1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -308,6 +308,7 @@ paludis-*.*.*.tar.bz2
/paludis/repositories/virtuals/installed_virtuals_repository_TEST
/paludis/repositories/virtuals/virtuals_repository_TEST
/paludis/repository_name_cache_TEST
+/paludis/resolver/resolver_TEST_blockers
/paludis/resolver/resolver_TEST_suggestions
/paludis/selection_TEST
/paludis/set_file_TEST
diff --git a/paludis/repositories/e/dep_parser.cc b/paludis/repositories/e/dep_parser.cc
index 20b9f09..e276003 100644
--- a/paludis/repositories/e/dep_parser.cc
+++ b/paludis/repositories/e/dep_parser.cc
@@ -103,11 +103,16 @@ namespace
std::string::size_type specstart(1);
if (2 <= s.length() && '!' == s.at(1))
{
- if (! eapi.supported()->dependency_spec_tree_parse_options()[dstpo_hard_soft_blocks])
+ if (! eapi.supported()->dependency_spec_tree_parse_options()[dstpo_double_bang_blocks])
throw EDepParseError(s, "Double-! blocks not allowed in this EAPI");
specstart = 2;
strong = true;
}
+ else
+ {
+ if (eapi.supported()->dependency_spec_tree_parse_options()[dstpo_single_bang_block_is_hard])
+ strong = true;
+ }
std::tr1::shared_ptr<BlockDepSpec> spec(new BlockDepSpec(
s,
diff --git a/paludis/repositories/e/dep_parser.se b/paludis/repositories/e/dep_parser.se
index aa7a372..25df525 100644
--- a/paludis/repositories/e/dep_parser.se
+++ b/paludis/repositories/e/dep_parser.se
@@ -9,6 +9,7 @@ make_enum_DependencySpecTreeParseOption()
key dstpo_disallow_any_use "Disallow || ( use? ( ... ) )"
key dstpo_uri_supports_arrow "Allow -> in FetchableURIDepSpec"
- key dstpo_hard_soft_blocks "Allow both !block and !!block"
+ key dstpo_double_bang_blocks "Allow both !block and !!block"
+ key dstpo_single_bang_block_is_hard "!block is a hard block"
}
diff --git a/paludis/repositories/e/eapis/2.conf b/paludis/repositories/e/eapis/2.conf
index 30a157c..a01193f 100644
--- a/paludis/repositories/e/eapis/2.conf
+++ b/paludis/repositories/e/eapis/2.conf
@@ -6,7 +6,7 @@ exported_name = 2
can_be_pbin = true
package_dep_spec_parse_options = allow_slot_deps allow_use_deps_portage
-dependency_spec_tree_parse_options = uri_supports_arrow hard_soft_blocks
+dependency_spec_tree_parse_options = uri_supports_arrow double_bang_blocks
ebuild_module_suffixes = 2 1 0
ebuild_functions = ${ebuild_functions} src_prepare src_configure
diff --git a/paludis/repositories/e/eapis/exheres-0.conf b/paludis/repositories/e/eapis/exheres-0.conf
index 1c66c21..8ac1115 100644
--- a/paludis/repositories/e/eapis/exheres-0.conf
+++ b/paludis/repositories/e/eapis/exheres-0.conf
@@ -9,7 +9,7 @@ package_dep_spec_parse_options = allow_slot_deps allow_use_deps \
allow_ranged_deps allow_tilde_greater_deps strict_parsing \
allow_slot_equal_deps allow_slot_star_deps allow_use_dep_defaults \
nice_equal_star disallow_nonranged_deps
-dependency_spec_tree_parse_options = disallow_any_use uri_supports_arrow
+dependency_spec_tree_parse_options = disallow_any_use uri_supports_arrow single_bang_block_is_hard
iuse_flag_parse_options = strict_parsing
version_spec_options = flexible_dashes flexible_dots ignore_case \
letters_anywhere dotted_suffixes
diff --git a/paludis/repositories/e/eapis/paludis-1.conf b/paludis/repositories/e/eapis/paludis-1.conf
index fdea12c..b07a5b3 100644
--- a/paludis/repositories/e/eapis/paludis-1.conf
+++ b/paludis/repositories/e/eapis/paludis-1.conf
@@ -8,7 +8,7 @@ can_be_pbin = true
package_dep_spec_parse_options = allow_slot_deps allow_use_deps allow_use_deps_portage allow_ranged_deps \
allow_repository_deps allow_tilde_greater_deps strict_parsing \
allow_slot_equal_deps allow_slot_star_deps allow_use_dep_defaults
-dependency_spec_tree_parse_options = disallow_any_use uri_supports_arrow hard_soft_blocks
+dependency_spec_tree_parse_options = disallow_any_use uri_supports_arrow double_bang_blocks
iuse_flag_parse_options = allow_iuse_defaults
merger_options = rewrite_symlinks allow_empty_dirs
breaks_portage = true
diff --git a/paludis/repositories/fake/fake_installed_repository.cc b/paludis/repositories/fake/fake_installed_repository.cc
index 99ca989..924362a 100644
--- a/paludis/repositories/fake/fake_installed_repository.cc
+++ b/paludis/repositories/fake/fake_installed_repository.cc
@@ -42,19 +42,22 @@ namespace paludis
std::tr1::shared_ptr<const MetadataValueKey<std::string> > format_key;
std::tr1::shared_ptr<const MetadataValueKey<FSEntry> > installed_root_key;
const bool supports_uninstall;
+ const bool is_suitable_destination;
- Implementation(const bool s) :
+ Implementation(const bool s, const bool b) :
format_key(new LiteralMetadataValueKey<std::string> (
"format", "format", mkt_significant, "installed_fake")),
installed_root_key(new LiteralMetadataValueKey<FSEntry> (
"installed_root", "installed_root", mkt_normal, FSEntry("/"))),
- supports_uninstall(s)
+ supports_uninstall(s),
+ is_suitable_destination(b)
{
}
};
}
-FakeInstalledRepository::FakeInstalledRepository(const Environment * const e, const RepositoryName & our_name, const bool supports_uninstall) :
+FakeInstalledRepository::FakeInstalledRepository(const Environment * const e, const RepositoryName & our_name,
+ const bool supports_uninstall, const bool i) :
FakeRepositoryBase(e, our_name, make_named_values<RepositoryCapabilities>(
value_for<n::destination_interface>(this),
value_for<n::e_interface>(static_cast<RepositoryEInterface *>(0)),
@@ -68,7 +71,7 @@ FakeInstalledRepository::FakeInstalledRepository(const Environment * const e, co
value_for<n::syncable_interface>(static_cast<RepositorySyncableInterface *>(0)),
value_for<n::virtuals_interface>(static_cast<RepositoryVirtualsInterface *>(0))
)),
- PrivateImplementationPattern<FakeInstalledRepository>(new Implementation<FakeInstalledRepository>(supports_uninstall)),
+ PrivateImplementationPattern<FakeInstalledRepository>(new Implementation<FakeInstalledRepository>(supports_uninstall, i)),
_imp(PrivateImplementationPattern<FakeInstalledRepository>::_imp)
{
add_metadata_key(_imp->format_key);
@@ -82,7 +85,7 @@ FakeInstalledRepository::~FakeInstalledRepository()
bool
FakeInstalledRepository::is_suitable_destination_for(const PackageID &) const
{
- return true;
+ return _imp->is_suitable_destination;
}
std::tr1::shared_ptr<const FakeInstalledRepository::ProvidesSequence>
diff --git a/paludis/repositories/fake/fake_installed_repository.hh b/paludis/repositories/fake/fake_installed_repository.hh
index 5f5e661..a566d3a 100644
--- a/paludis/repositories/fake/fake_installed_repository.hh
+++ b/paludis/repositories/fake/fake_installed_repository.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -61,7 +61,8 @@ namespace paludis
///\name Basic operations
///\{
- FakeInstalledRepository(const Environment * const, const RepositoryName &, const bool supports_uninstall = true);
+ FakeInstalledRepository(const Environment * const, const RepositoryName &, const bool supports_uninstall = true,
+ const bool suitable_destination = true);
~FakeInstalledRepository();
///\}
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index 098a6fe..3838fb1 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -77,20 +77,44 @@ if ENABLE_NEW_RESOLVER
noinst_LIBRARIES = libpaludisresolver.a
TESTS = \
+ resolver_TEST_blockers \
resolver_TEST_suggestions
endif
check_PROGRAMS = $(TESTS)
check_SCRIPTS = \
+ resolver_TEST_blockers_setup.sh resolver_TEST_blockers_cleanup.sh
resolver_TEST_suggestions_setup.sh resolver_TEST_suggestions_cleanup.sh
+check_LIBRARIES = libpaludisresolvertest.a
+
+libpaludisresolvertest_a_SOURCES = \
+ resolver_test.hh \
+ resolver_test.cc
+
+resolver_TEST_blockers_SOURCES = resolver_TEST_blockers.cc
+
+resolver_TEST_blockers_LDADD = \
+ libpaludisresolvertest.a \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/libpaludis_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
+ libpaludisresolver.a \
+ $(DYNAMIC_LD_LIBS)
+
+resolver_TEST_blockers_CXXFLAGS = $(AM_CXXFLAGS) @PALUDIS_CXXFLAGS_NO_DEBUGGING@
resolver_TEST_suggestions_SOURCES = resolver_TEST_suggestions.cc
resolver_TEST_suggestions_LDADD = \
+ libpaludisresolvertest.a \
$(top_builddir)/paludis/util/test_extras.o \
$(top_builddir)/test/libtest.a \
$(top_builddir)/paludis/environments/test/libpaludistestenvironment_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository_@PALUDIS_PC_SLOT@.la \
$(top_builddir)/paludis/libpaludis_@PALUDIS_PC_SLOT@.la \
$(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
libpaludisresolver.a \
diff --git a/paludis/resolver/resolver.cc b/paludis/resolver/resolver.cc
index c0337e7..792ac3d 100644
--- a/paludis/resolver/resolver.cc
+++ b/paludis/resolver/resolver.cc
@@ -729,33 +729,41 @@ Resolver::_resolve_arrows()
c_end(i->second->constraints()->end()) ;
c != c_end ; ++c)
{
- if ((*c)->spec().if_block())
- {
- /* todo: strong blocks do impose arrows */
- continue;
- }
-
GetDependencyReason gdr;
const DependencyReason * if_dependency_reason((*c)->reason()->accept_returning<const DependencyReason *>(gdr));
if (! if_dependency_reason)
- continue;
+ continue;
const QPN_S from_qpns(if_dependency_reason->from_id());
const std::tr1::shared_ptr<Resolution> resolution(_resolution_for_qpn_s(from_qpns, false));
- ArrowInfo a(*if_dependency_reason);
- if (a.causes_pre_arrow)
+ if ((*c)->spec().if_block())
{
- int ignorable_pass(0);
- if (_already_met(if_dependency_reason->sanitised_dependency()))
- ignorable_pass = 1;
- else if (a.ignorable)
- ignorable_pass = 2;
-
- resolution->arrows()->push_back(make_shared_ptr(new Arrow(make_named_values<Arrow>(
- value_for<n::ignorable_pass>(ignorable_pass),
- value_for<n::to_qpn_s>(i->first)
- ))));
+ if ((*c)->spec().if_block()->strong())
+ {
+ resolution->arrows()->push_back(make_shared_ptr(new Arrow(make_named_values<Arrow>(
+ value_for<n::ignorable_pass>(0),
+ value_for<n::to_qpn_s>(i->first)
+ ))));
+ }
+ continue;
+ }
+ else
+ {
+ ArrowInfo a(*if_dependency_reason);
+ if (a.causes_pre_arrow)
+ {
+ int ignorable_pass(0);
+ if (_already_met(if_dependency_reason->sanitised_dependency()))
+ ignorable_pass = 1;
+ else if (a.ignorable)
+ ignorable_pass = 2;
+
+ resolution->arrows()->push_back(make_shared_ptr(new Arrow(make_named_values<Arrow>(
+ value_for<n::ignorable_pass>(ignorable_pass),
+ value_for<n::to_qpn_s>(i->first)
+ ))));
+ }
}
}
}
diff --git a/paludis/resolver/resolver_TEST_blockers.cc b/paludis/resolver/resolver_TEST_blockers.cc
new file mode 100644
index 0000000..a05c9cf
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_blockers.cc
@@ -0,0 +1,98 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/resolver/resolver.hh>
+#include <paludis/resolver/resolver_functions.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/constraint.hh>
+#include <paludis/resolver/qpn_s.hh>
+#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/repository_factory.hh>
+#include <paludis/package_database.hh>
+
+#include <paludis/resolver/resolver_test.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+
+#include <list>
+#include <tr1/functional>
+#include <algorithm>
+#include <map>
+
+using namespace paludis;
+using namespace paludis::resolver;
+using namespace paludis::resolver::resolver_test;
+using namespace test;
+
+namespace
+{
+ struct ResolverBlockersTestCase : ResolverTestCase
+ {
+ ResolverBlockersTestCase(const std::string & s) :
+ ResolverTestCase("blockers", s)
+ {
+ }
+ };
+}
+
+namespace test_cases
+{
+ struct TestHardBlocker : ResolverBlockersTestCase
+ {
+ TestHardBlocker() : ResolverBlockersTestCase("hard") { }
+
+ void run()
+ {
+ install("hard", "a-pkg", "1");
+ install("hard", "z-pkg", "1");
+
+ std::tr1::shared_ptr<const ResolutionLists> resolutions(get_resolutions("hard/target"));
+
+ {
+ TestMessageSuffix s("errors");
+ check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ .finished()
+ );
+ }
+
+ {
+ TestMessageSuffix s("ordered");
+ check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ .qpn(QualifiedPackageName("hard/a-pkg"))
+ .qpn(QualifiedPackageName("hard/z-pkg"))
+ .qpn(QualifiedPackageName("hard/target"))
+ .finished()
+ );
+ }
+ }
+ } test_hard_blocker;
+}
+
diff --git a/paludis/resolver/resolver_TEST_blockers_cleanup.sh b/paludis/resolver/resolver_TEST_blockers_cleanup.sh
new file mode 100755
index 0000000..204c991
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_blockers_cleanup.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d resolver_TEST_blockers_dir ] ; then
+ rm -fr resolver_TEST_blockers_dir
+else
+ true
+fi
+
diff --git a/paludis/resolver/resolver_TEST_blockers_setup.sh b/paludis/resolver/resolver_TEST_blockers_setup.sh
new file mode 100755
index 0000000..afea487
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_blockers_setup.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir resolver_TEST_blockers_dir || exit 1
+cd resolver_TEST_blockers_dir || exit 1
+
+mkdir -p build
+mkdir -p distdir
+mkdir -p installed
+
+mkdir -p repo/{profiles/profile,metadata}
+
+cd repo
+echo "repo" > profiles/repo_name
+: > metadata/categories.conf
+
+# hard
+echo 'hard' >> metadata/categories.conf
+
+mkdir -p 'packages/hard/target'
+cat <<END > packages/hard/target/target-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="
+ ( !hard/a-pkg[<2] !hard/z-pkg[<2] )
+ "
+END
+
+mkdir -p 'packages/hard/a-pkg'
+cat <<END > packages/hard/a-pkg/a-pkg-2.exheres-0
+SUMMARY="dep"
+PLATFORMS="test"
+SLOT="0"
+END
+
+mkdir -p 'packages/hard/z-pkg'
+cat <<END > packages/hard/z-pkg/z-pkg-2.exheres-0
+SUMMARY="dep"
+PLATFORMS="test"
+SLOT="0"
+END
+
+cd ..
+
diff --git a/paludis/resolver/resolver_TEST_suggestions.cc b/paludis/resolver/resolver_TEST_suggestions.cc
index 85426a8..9f9c75b 100644
--- a/paludis/resolver/resolver_TEST_suggestions.cc
+++ b/paludis/resolver/resolver_TEST_suggestions.cc
@@ -37,8 +37,11 @@
#include <paludis/user_dep_spec.hh>
#include <paludis/repository_factory.hh>
#include <paludis/package_database.hh>
+
+#include <paludis/resolver/resolver_test.hh>
#include <test/test_runner.hh>
#include <test/test_framework.hh>
+
#include <list>
#include <tr1/functional>
#include <algorithm>
@@ -46,242 +49,16 @@
using namespace paludis;
using namespace paludis::resolver;
+using namespace paludis::resolver::resolver_test;
using namespace test;
namespace
{
- std::string from_keys(const std::tr1::shared_ptr<const Map<std::string, std::string> > & m,
- const std::string & k)
- {
- Map<std::string, std::string>::ConstIterator mm(m->find(k));
- if (m->end() == mm)
- return "";
- else
- return mm->second;
- }
-
- typedef std::map<QPN_S, std::tr1::shared_ptr<Constraints> > InitialConstraints;
-
- bool care_about_dep_fn(const QPN_S &, const std::tr1::shared_ptr<const Resolution> &, const SanitisedDependency &)
+ struct ResolverSuggestionsTestCase : ResolverTestCase
{
- return true;
- }
-
- const std::tr1::shared_ptr<Constraints> initial_constraints_for_fn(
- const InitialConstraints & initial_constraints,
- const QPN_S & qpn_s)
- {
- InitialConstraints::const_iterator i(initial_constraints.find(qpn_s));
- if (i == initial_constraints.end())
- return make_shared_ptr(new Constraints);
- else
- return i->second;
- }
-
- std::tr1::shared_ptr<QPN_S_Sequence> get_qpn_s_s_for_fn(const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const Reason> &)
- {
- std::tr1::shared_ptr<QPN_S_Sequence> result(new QPN_S_Sequence);
- result->push_back(QPN_S(spec, make_shared_ptr(new SlotName("0"))));
- return result;
- }
-
- struct IsSuggestionVisitor
- {
- bool is_suggestion;
-
- IsSuggestionVisitor() :
- is_suggestion(true)
- {
- }
-
- void visit(const DependencyRequiredLabel &)
- {
- is_suggestion = false;
- }
-
- void visit(const DependencyRecommendedLabel &)
- {
- is_suggestion = false;
- }
-
- void visit(const DependencySuggestedLabel &)
- {
- }
- };
-
- bool is_suggestion(const SanitisedDependency & dep)
- {
- if (dep.active_dependency_labels()->suggest_labels()->empty())
- return false;
-
- IsSuggestionVisitor v;
- std::for_each(indirect_iterator(dep.active_dependency_labels()->suggest_labels()->begin()),
- indirect_iterator(dep.active_dependency_labels()->suggest_labels()->end()),
- accept_visitor(v));
- return v.is_suggestion;
- }
-
- bool take_dependency_fn(
- const QPN_S &,
- const SanitisedDependency & dep,
- const std::tr1::shared_ptr<const Reason> &)
- {
- return ! is_suggestion(dep);
- }
-
- UseInstalled get_use_installed_fn(
- const QPN_S &,
- const PackageDepSpec &,
- const std::tr1::shared_ptr<const Reason> &)
- {
- return ui_never;
- }
-
- struct ResolverSuggestionsTestCase : TestCase
- {
- TestEnvironment env;
- std::tr1::shared_ptr<Repository> repo, inst_repo;
-
ResolverSuggestionsTestCase(const std::string & s) :
- TestCase(s)
+ ResolverTestCase("suggestions", s)
{
- std::tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
- keys->insert("format", "exheres");
- keys->insert("names_cache", "/var/empty");
- keys->insert("location", stringify(FSEntry::cwd() / "resolver_TEST_suggestions_dir" / "repo"));
- keys->insert("profiles", stringify(FSEntry::cwd() / "resolver_TEST_suggestions_dir" / "repo/profiles/profile"));
- keys->insert("layout", "exheres");
- keys->insert("eapi_when_unknown", "exheres-0");
- keys->insert("eapi_when_unspecified", "exheres-0");
- keys->insert("profile_eapi", "exheres-0");
- keys->insert("distdir", stringify(FSEntry::cwd() / "resolver_TEST_suggestions_dir" / "distdir"));
- keys->insert("builddir", stringify(FSEntry::cwd() / "resolver_TEST_suggestions_dir" / "build"));
- repo = RepositoryFactory::get_instance()->create(&env,
- std::tr1::bind(from_keys, keys, std::tr1::placeholders::_1));
- env.package_database()->add_repository(1, repo);
-
- keys.reset(new Map<std::string, std::string>);
- keys->insert("format", "exndbam");
- keys->insert("names_cache", "/var/empty");
- keys->insert("provides_cache", "/var/empty");
- keys->insert("location", stringify(FSEntry::cwd() / "resolver_TEST_suggestions_dir" / "installed"));
- keys->insert("builddir", stringify(FSEntry::cwd() / "resolver_TEST_suggestions_dir" / "build"));
- inst_repo = RepositoryFactory::get_instance()->create(&env,
- std::tr1::bind(from_keys, keys, std::tr1::placeholders::_1));
- env.package_database()->add_repository(1, inst_repo);
- }
-
- const std::tr1::shared_ptr<const ResolutionLists> get_resolutions(const PackageDepSpec & target)
- {
- InitialConstraints initial_constraints;
-
- while (true)
- {
- try
- {
- Resolver resolver(&env, make_named_values<ResolverFunctions>(
- value_for<n::care_about_dep_fn>(&care_about_dep_fn),
- value_for<n::get_initial_constraints_for_fn>(
- std::tr1::bind(&initial_constraints_for_fn, std::tr1::ref(initial_constraints),
- std::tr1::placeholders::_1)),
- value_for<n::get_qpn_s_s_for_fn>(&get_qpn_s_s_for_fn),
- value_for<n::get_use_installed_fn>(&get_use_installed_fn),
- value_for<n::take_dependency_fn>(&take_dependency_fn)
- ));
- resolver.add_target(target);
- resolver.resolve();
- return resolver.resolution_lists();
- }
- catch (const SuggestRestart & e)
- {
- initial_constraints.insert(std::make_pair(e.qpn_s(), make_shared_ptr(new Constraints))).first->second->add(
- e.suggested_preset());
- }
- }
- }
-
- const std::tr1::shared_ptr<const ResolutionLists> get_resolutions(const std::string & target)
- {
- PackageDepSpec target_spec(parse_user_package_dep_spec(target, &env, UserPackageDepSpecOptions()));
- return get_resolutions(target_spec);
- }
-
- struct ResolutionListChecks
- {
- typedef std::tr1::function<bool (const std::tr1::shared_ptr<const Resolution> &) > CheckFunction;
- typedef std::tr1::function<std::string (const std::tr1::shared_ptr<const Resolution> &) > MessageFunction;
- typedef std::list<std::pair<CheckFunction, MessageFunction> > List;
- List checks;
-
- static bool check_qpn(const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r)
- {
- if ((! r) || (! r->decision()) || (! r->decision()->if_package_id()))
- return false;
-
- return r->decision()->if_package_id()->name() == q;
- }
-
- static std::string check_generic_msg(const std::string & q, const std::tr1::shared_ptr<const Resolution> & r)
- {
- if (! r)
- return "Expected " + stringify(q) + " but got finished";
- else if (! r->decision())
- return "Expected " + stringify(q) + " but got undecided for " + stringify(r->qpn_s());
- else if (! r->decision()->if_package_id())
- return "Expected " + stringify(q) + " but got decided nothing (kind " + stringify(r->decision()->kind()) + ") for "
- + stringify(r->qpn_s());
- else
- return "Expected " + stringify(q) + " but got " + stringify(r->decision()->if_package_id()->name()) + " for "
- + stringify(r->qpn_s());
- }
-
- static std::string check_qpn_msg(const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r)
- {
- return check_generic_msg(stringify(q), r);
- }
-
- static bool check_finished(const std::tr1::shared_ptr<const Resolution> & r)
- {
- return ! r;
- }
-
- static std::string check_finished_msg(const std::tr1::shared_ptr<const Resolution> & r)
- {
- return check_generic_msg("finished", r);
- }
-
- ResolutionListChecks & qpn(const QualifiedPackageName & q)
- {
- checks.push_back(std::make_pair(
- std::tr1::bind(&check_qpn, q, std::tr1::placeholders::_1),
- std::tr1::bind(&check_qpn_msg, q, std::tr1::placeholders::_1)
- ));
- return *this;
- }
-
- ResolutionListChecks & finished()
- {
- checks.push_back(std::make_pair(
- &check_finished,
- &check_finished_msg
- ));
- return *this;
- }
- };
-
- void check_resolution_list(const std::tr1::shared_ptr<const Resolutions> & list, const ResolutionListChecks & checks)
- {
- Resolutions::ConstIterator r(list->begin()), r_end(list->end());
- for (ResolutionListChecks::List::const_iterator c(checks.checks.begin()), c_end(checks.checks.end()) ;
- c != c_end ; ++c)
- {
- if (r == r_end)
- TEST_CHECK_MESSAGE(c->first(make_null_shared_ptr()), c->second(make_null_shared_ptr()));
- else
- TEST_CHECK_MESSAGE(c->first(*r), c->second(*r));
- ++r;
- }
}
};
}
diff --git a/paludis/resolver/resolver_test.cc b/paludis/resolver/resolver_test.cc
new file mode 100644
index 0000000..b2053ea
--- /dev/null
+++ b/paludis/resolver/resolver_test.cc
@@ -0,0 +1,296 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/resolver/resolver_test.hh>
+#include <paludis/resolver/constraint.hh>
+#include <paludis/resolver/qpn_s.hh>
+#include <paludis/resolver/resolver.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/resolver_functions.hh>
+#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/decision.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/repositories/fake/fake_installed_repository.hh>
+#include <paludis/repository_factory.hh>
+#include <paludis/package_database.hh>
+#include <paludis/user_dep_spec.hh>
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::resolver;
+using namespace paludis::resolver::resolver_test;
+using namespace test;
+
+std::string
+paludis::resolver::resolver_test::from_keys(const std::tr1::shared_ptr<const Map<std::string, std::string> > & m,
+ const std::string & k)
+{
+ Map<std::string, std::string>::ConstIterator mm(m->find(k));
+ if (m->end() == mm)
+ return "";
+ else
+ return mm->second;
+}
+
+bool
+paludis::resolver::resolver_test::care_about_dep_fn(const QPN_S &, const std::tr1::shared_ptr<const Resolution> &, const SanitisedDependency &)
+{
+ return true;
+}
+
+const std::tr1::shared_ptr<Constraints>
+paludis::resolver::resolver_test::initial_constraints_for_fn(
+ const InitialConstraints & initial_constraints,
+ const QPN_S & qpn_s)
+{
+ InitialConstraints::const_iterator i(initial_constraints.find(qpn_s));
+ if (i == initial_constraints.end())
+ return make_shared_ptr(new Constraints);
+ else
+ return i->second;
+}
+
+std::tr1::shared_ptr<QPN_S_Sequence>
+paludis::resolver::resolver_test::get_qpn_s_s_for_fn(const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const Reason> &)
+{
+ std::tr1::shared_ptr<QPN_S_Sequence> result(new QPN_S_Sequence);
+ result->push_back(QPN_S(spec, make_shared_ptr(new SlotName("0"))));
+ return result;
+}
+
+namespace
+{
+ struct IsSuggestionVisitor
+ {
+ bool is_suggestion;
+
+ IsSuggestionVisitor() :
+ is_suggestion(true)
+ {
+ }
+
+ void visit(const DependencyRequiredLabel &)
+ {
+ is_suggestion = false;
+ }
+
+ void visit(const DependencyRecommendedLabel &)
+ {
+ is_suggestion = false;
+ }
+
+ void visit(const DependencySuggestedLabel &)
+ {
+ }
+ };
+}
+
+bool
+paludis::resolver::resolver_test::is_suggestion(const SanitisedDependency & dep)
+{
+ if (dep.active_dependency_labels()->suggest_labels()->empty())
+ return false;
+
+ IsSuggestionVisitor v;
+ std::for_each(indirect_iterator(dep.active_dependency_labels()->suggest_labels()->begin()),
+ indirect_iterator(dep.active_dependency_labels()->suggest_labels()->end()),
+ accept_visitor(v));
+ return v.is_suggestion;
+}
+
+bool
+paludis::resolver::resolver_test::take_dependency_fn(
+ const QPN_S &,
+ const SanitisedDependency & dep,
+ const std::tr1::shared_ptr<const Reason> &)
+{
+ return ! is_suggestion(dep);
+}
+
+UseInstalled
+paludis::resolver::resolver_test::get_use_installed_fn(
+ const QPN_S &,
+ const PackageDepSpec &,
+ const std::tr1::shared_ptr<const Reason> &)
+{
+ return ui_never;
+}
+
+ResolverTestCase::ResolverTestCase(const std::string & t, const std::string & s) :
+ TestCase(s)
+{
+ std::tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "exheres");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", stringify(FSEntry::cwd() / ("resolver_TEST_" + t + "_dir") / "repo"));
+ keys->insert("profiles", stringify(FSEntry::cwd() / ("resolver_TEST_" + t + "_dir") / "repo/profiles/profile"));
+ keys->insert("layout", "exheres");
+ keys->insert("eapi_when_unknown", "exheres-0");
+ keys->insert("eapi_when_unspecified", "exheres-0");
+ keys->insert("profile_eapi", "exheres-0");
+ keys->insert("distdir", stringify(FSEntry::cwd() / ("resolver_TEST_" + t + "_dir") / "distdir"));
+ keys->insert("builddir", stringify(FSEntry::cwd() / ("resolver_TEST_" + t + "_dir") / "build"));
+ repo = RepositoryFactory::get_instance()->create(&env,
+ std::tr1::bind(from_keys, keys, std::tr1::placeholders::_1));
+ env.package_database()->add_repository(1, repo);
+
+ keys.reset(new Map<std::string, std::string>);
+ keys->insert("format", "exndbam");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", stringify(FSEntry::cwd() / ("resolver_TEST_" + t + "_dir") / "installed"));
+ keys->insert("builddir", stringify(FSEntry::cwd() / ("resolver_TEST_" + t + "_dir") / "build"));
+ inst_repo = RepositoryFactory::get_instance()->create(&env,
+ std::tr1::bind(from_keys, keys, std::tr1::placeholders::_1));
+ env.package_database()->add_repository(1, inst_repo);
+
+ fake_inst_repo.reset(new FakeInstalledRepository(&env, RepositoryName("fake-inst"), true, false));
+ env.package_database()->add_repository(1, fake_inst_repo);
+}
+
+const std::tr1::shared_ptr<const ResolutionLists>
+ResolverTestCase::get_resolutions(const PackageDepSpec & target)
+{
+ InitialConstraints initial_constraints;
+
+ while (true)
+ {
+ try
+ {
+ Resolver resolver(&env, make_named_values<ResolverFunctions>(
+ value_for<n::care_about_dep_fn>(&care_about_dep_fn),
+ value_for<n::get_initial_constraints_for_fn>(
+ std::tr1::bind(&initial_constraints_for_fn, std::tr1::ref(initial_constraints),
+ std::tr1::placeholders::_1)),
+ value_for<n::get_qpn_s_s_for_fn>(&get_qpn_s_s_for_fn),
+ value_for<n::get_use_installed_fn>(&get_use_installed_fn),
+ value_for<n::take_dependency_fn>(&take_dependency_fn)
+ ));
+ resolver.add_target(target);
+ resolver.resolve();
+ return resolver.resolution_lists();
+ }
+ catch (const SuggestRestart & e)
+ {
+ initial_constraints.insert(std::make_pair(e.qpn_s(), make_shared_ptr(new Constraints))).first->second->add(
+ e.suggested_preset());
+ }
+ }
+}
+
+const std::tr1::shared_ptr<const ResolutionLists>
+ResolverTestCase::get_resolutions(const std::string & target)
+{
+ PackageDepSpec target_spec(parse_user_package_dep_spec(target, &env, UserPackageDepSpecOptions()));
+ return get_resolutions(target_spec);
+}
+
+bool
+ResolverTestCase::ResolutionListChecks::check_qpn(const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r)
+{
+ if ((! r) || (! r->decision()) || (! r->decision()->if_package_id()))
+ return false;
+
+ return r->decision()->if_package_id()->name() == q;
+}
+
+std::string
+ResolverTestCase::ResolutionListChecks::check_generic_msg(const std::string & q, const std::tr1::shared_ptr<const Resolution> & r)
+{
+ if (! r)
+ return "Expected " + stringify(q) + " but got finished";
+ else if (! r->decision())
+ return "Expected " + stringify(q) + " but got undecided for " + stringify(r->qpn_s());
+ else if (! r->decision()->if_package_id())
+ return "Expected " + stringify(q) + " but got decided nothing (kind " + stringify(r->decision()->kind()) + ") for "
+ + stringify(r->qpn_s());
+ else
+ return "Expected " + stringify(q) + " but got " + stringify(r->decision()->if_package_id()->name()) + " for "
+ + stringify(r->qpn_s());
+}
+
+std::string
+ResolverTestCase::ResolutionListChecks::check_qpn_msg(const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r)
+{
+ return check_generic_msg(stringify(q), r);
+}
+
+bool
+ResolverTestCase::ResolutionListChecks::check_finished(const std::tr1::shared_ptr<const Resolution> & r)
+{
+ return ! r;
+}
+
+std::string
+ResolverTestCase::ResolutionListChecks::check_finished_msg(const std::tr1::shared_ptr<const Resolution> & r)
+{
+ return check_generic_msg("finished", r);
+}
+
+ResolverTestCase::ResolutionListChecks &
+ResolverTestCase::ResolutionListChecks::qpn(const QualifiedPackageName & q)
+{
+ checks.push_back(std::make_pair(
+ std::tr1::bind(&check_qpn, q, std::tr1::placeholders::_1),
+ std::tr1::bind(&check_qpn_msg, q, std::tr1::placeholders::_1)
+ ));
+ return *this;
+}
+
+ResolverTestCase::ResolutionListChecks &
+ResolverTestCase::ResolutionListChecks::finished()
+{
+ checks.push_back(std::make_pair(
+ &check_finished,
+ &check_finished_msg
+ ));
+ return *this;
+}
+
+void
+ResolverTestCase::check_resolution_list(
+ const std::tr1::shared_ptr<const Resolutions> & list, const ResolutionListChecks & checks)
+{
+ Resolutions::ConstIterator r(list->begin()), r_end(list->end());
+ for (ResolutionListChecks::List::const_iterator c(checks.checks.begin()), c_end(checks.checks.end()) ;
+ c != c_end ; ++c)
+ {
+ if (r == r_end)
+ TEST_CHECK_MESSAGE(c->first(make_null_shared_ptr()), c->second(make_null_shared_ptr()));
+ else
+ TEST_CHECK_MESSAGE(c->first(*r), c->second(*r));
+ ++r;
+ }
+}
+
+void
+ResolverTestCase::install(const std::string & c, const std::string & p, const std::string & v)
+{
+ fake_inst_repo->add_version(c, p, v);
+}
+
diff --git a/paludis/resolver/resolver_test.hh b/paludis/resolver/resolver_test.hh
new file mode 100644
index 0000000..fc9219c
--- /dev/null
+++ b/paludis/resolver/resolver_test.hh
@@ -0,0 +1,114 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLVER_TEST_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLVER_TEST_HH 1
+
+#include <paludis/resolver/qpn_s-fwd.hh>
+#include <paludis/resolver/constraint-fwd.hh>
+#include <paludis/resolver/resolution-fwd.hh>
+#include <paludis/resolver/sanitised_dependencies-fwd.hh>
+#include <paludis/resolver/reason-fwd.hh>
+#include <paludis/resolver/use_installed-fwd.hh>
+#include <paludis/resolver/resolutions-fwd.hh>
+#include <paludis/repositories/fake/fake_installed_repository.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/map-fwd.hh>
+#include <paludis/dep_spec-fwd.hh>
+#include <test/test_framework.hh>
+#include <tr1/memory>
+#include <string>
+#include <map>
+#include <list>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ namespace resolver_test
+ {
+ std::string from_keys(const std::tr1::shared_ptr<const Map<std::string, std::string> > & m,
+ const std::string & k);
+
+ typedef std::map<QPN_S, std::tr1::shared_ptr<Constraints> > InitialConstraints;
+
+ bool care_about_dep_fn(const QPN_S &, const std::tr1::shared_ptr<const Resolution> &, const SanitisedDependency &);
+
+ const std::tr1::shared_ptr<Constraints> initial_constraints_for_fn(
+ const InitialConstraints & initial_constraints,
+ const QPN_S & qpn_s);
+
+ std::tr1::shared_ptr<QPN_S_Sequence> get_qpn_s_s_for_fn(const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const Reason> &);
+
+ bool is_suggestion(const SanitisedDependency & dep);
+
+ bool take_dependency_fn(
+ const QPN_S &,
+ const SanitisedDependency & dep,
+ const std::tr1::shared_ptr<const Reason> &);
+
+ UseInstalled get_use_installed_fn(
+ const QPN_S &,
+ const PackageDepSpec &,
+ const std::tr1::shared_ptr<const Reason> &);
+
+ struct ResolverTestCase : test::TestCase
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<Repository> repo, inst_repo;
+ std::tr1::shared_ptr<FakeInstalledRepository> fake_inst_repo;
+
+ ResolverTestCase(const std::string & group, const std::string & test_name);
+
+ const std::tr1::shared_ptr<const ResolutionLists> get_resolutions(const PackageDepSpec & target);
+
+ const std::tr1::shared_ptr<const ResolutionLists> get_resolutions(const std::string & target);
+
+ struct ResolutionListChecks
+ {
+ typedef std::tr1::function<bool (const std::tr1::shared_ptr<const Resolution> &) > CheckFunction;
+ typedef std::tr1::function<std::string (const std::tr1::shared_ptr<const Resolution> &) > MessageFunction;
+ typedef std::list<std::pair<CheckFunction, MessageFunction> > List;
+ List checks;
+
+ static bool check_qpn(const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r);
+
+ static std::string check_generic_msg(const std::string & q, const std::tr1::shared_ptr<const Resolution> & r);
+
+ static std::string check_qpn_msg(const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r);
+
+ static bool check_finished(const std::tr1::shared_ptr<const Resolution> & r);
+
+ static std::string check_finished_msg(const std::tr1::shared_ptr<const Resolution> & r);
+
+ ResolutionListChecks & qpn(const QualifiedPackageName & q);
+
+ ResolutionListChecks & finished();
+ };
+
+ void check_resolution_list(const std::tr1::shared_ptr<const Resolutions> & list, const ResolutionListChecks & checks);
+
+ void install(const std::string & c, const std::string & p, const std::string & v);
+ };
+ }
+ }
+}
+
+#endif