aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-12 20:26:47 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-12 21:33:35 +0100
commit852176d7e3e3ef7aeeef793d8a28a82b28e77025 (patch)
tree7c4206b628ec4da95865af138f40c056f4d0ccf5
parentf197a47197b1989a6bf42d947ef752ade358a36e (diff)
downloadpaludis-852176d7e3e3ef7aeeef793d8a28a82b28e77025.tar.gz
paludis-852176d7e3e3ef7aeeef793d8a28a82b28e77025.tar.xz
Handle something being a suggestion then a dep properly
-rw-r--r--.gitignore1
-rw-r--r--paludis/resolver/Makefile.am44
-rw-r--r--paludis/resolver/resolver.cc27
-rw-r--r--paludis/resolver/resolver.hh2
-rw-r--r--paludis/resolver/resolver_TEST_suggestions.cc325
-rwxr-xr-xpaludis/resolver/resolver_TEST_suggestions_cleanup.sh9
-rwxr-xr-xpaludis/resolver/resolver_TEST_suggestions_setup.sh50
7 files changed, 445 insertions, 13 deletions
diff --git a/.gitignore b/.gitignore
index d14dba4..9bbcb55 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_suggestions
/paludis/selection_TEST
/paludis/set_file_TEST
/paludis/stringify_formatter_TEST
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index 3388ac1..0f6e2e1 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -14,8 +14,6 @@ BUILT_SOURCES = \
destination_types-se.hh destination_types-se.cc \
use_installed-se.hh use_installed-se.cc
-TESTS =
-
noinst_HEADERS = \
arrow.hh arrow-fwd.hh \
constraint.hh constraint-fwd.hh \
@@ -49,17 +47,55 @@ libpaludisresolver_a_SOURCES = \
suggest_restart.cc \
use_installed.cc
-TESTS_ENVIRONMENT = env PALUDIS_OPTIONS="" \
+TESTS_ENVIRONMENT = env \
+ PALUDIS_OPTIONS="" \
+ TEST_OUTPUT_WRAPPER="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/outputwrapper`" \
+ PALUDIS_OUTPUTWRAPPER_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \
+ PALUDIS_EBUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_srcdir)/paludis/repositories/e/ebuild/`" \
+ PALUDIS_EBUILD_DIR_FALLBACK="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/e/ebuild/`" \
+ PALUDIS_EXTRA_EBUILD_MODULES_DIRS="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \
+ PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/repositories/e/eapis/" \
+ PALUDIS_SUFFIXES_FILE="$(top_srcdir)/paludis/repositories/e/ebuild_entries_suffixes.conf" \
+ PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
+ PALUDIS_DISTRIBUTION="gentoo" \
+ PALUDIS_OPTIONS="" \
+ PALUDIS_FETCHERS_DIR="$(top_srcdir)/paludis/fetchers/" \
+ PALUDIS_SKIP_CONFIG="yes" \
TEST_SCRIPT_DIR="$(srcdir)/" \
PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
- PALUDIS_DISTRIBUTION="gentoo" \
+ PALUDIS_NO_CHOWN="yes" \
+ PALUDIS_TESTS_KEEP_STDERR="yes" \
+ PALUDIS_DEFAULT_OUTPUT_CONF="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_srcdir)/paludis/environments/paludis/tests_output.conf`" \
+ PALUDIS_OUTPUT_MANAGERS_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_srcdir)/paludis/environments/paludis/output_managers/`" \
+ LD_LIBRARY_PATH="`echo $$LD_LIBRARY_PATH: | sed -e 's,^:,,'`` \
+ $(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/e/`:` \
+ $(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/e/.libs/`" \
bash $(top_srcdir)/test/run_test.sh
if ENABLE_NEW_RESOLVER
noinst_LIBRARIES = libpaludisresolver.a
+
+TESTS = \
+ resolver_TEST_suggestions
endif
+
check_PROGRAMS = $(TESTS)
+check_SCRIPTS = \
+ resolver_TEST_suggestions_setup.sh resolver_TEST_suggestions_cleanup.sh
+
+resolver_TEST_suggestions_SOURCES = resolver_TEST_suggestions.cc
+
+resolver_TEST_suggestions_LDADD = \
+ $(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/libpaludis_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
+ libpaludisresolver.a \
+ $(DYNAMIC_LD_LIBS)
+
+resolver_TEST_suggestions_CXXFLAGS = $(AM_CXXFLAGS) @PALUDIS_CXXFLAGS_NO_DEBUGGING@
built-sources : $(BUILT_SOURCES)
for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
diff --git a/paludis/resolver/resolver.cc b/paludis/resolver/resolver.cc
index 55d157f..c7ba0a0 100644
--- a/paludis/resolver/resolver.cc
+++ b/paludis/resolver/resolver.cc
@@ -103,31 +103,39 @@ Resolver::resolve()
{
Context context("When finding an appropriate resolution:");
- _resolve_dependencies();
+ _resolve_decide_with_dependencies();
_resolve_destinations();
_resolve_arrows();
_resolve_order();
}
void
-Resolver::_resolve_dependencies()
+Resolver::_resolve_decide_with_dependencies()
{
- Context context("When resolving dependencies recursively:");
+ Context context("When resolving and adding dependencies recursively:");
- bool done(false);
- while (! done)
+ enum State { deciding_non_suggestions, deciding_suggestions, finished } state = deciding_non_suggestions;
+ bool changed(true);
+ while (true)
{
- done = true;
+ if (! changed)
+ state = State(state + 1);
+ if (state == finished)
+ break;
+ changed = false;
for (ResolutionsByQPN_SMap::iterator i(_imp->resolutions_by_qpn_s.begin()), i_end(_imp->resolutions_by_qpn_s.end()) ;
i != i_end ; ++i)
{
if (i->second->decision())
continue;
+ if (i->second->constraints()->all_untaken() && state == deciding_non_suggestions)
+ continue;
+
_imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent());
- done = false;
+ changed = true;
_decide(i->first, i->second);
switch (i->second->decision()->kind())
@@ -482,6 +490,9 @@ Resolver::_verify_new_constraint(const QPN_S & qpn_s,
}
}
+ if (ok && ! constraint->untaken())
+ ok = resolution->decision()->taken();
+
if (! ok)
_made_wrong_decision(qpn_s, resolution, constraint);
}
@@ -546,7 +557,7 @@ Resolver::_make_constraint_for_preloading(
value_for<n::reason>(reason),
value_for<n::spec>(d->if_package_id()->uniquely_identifying_spec()),
value_for<n::to_destinations>(DestinationTypes()),
- value_for<n::untaken>(false),
+ value_for<n::untaken>(! d->taken()),
value_for<n::use_installed>(_imp->fns.get_use_installed_fn()(
qpn_s, d->if_package_id()->uniquely_identifying_spec(), reason))
)));
diff --git a/paludis/resolver/resolver.hh b/paludis/resolver/resolver.hh
index 108b230..15b658f 100644
--- a/paludis/resolver/resolver.hh
+++ b/paludis/resolver/resolver.hh
@@ -103,7 +103,7 @@ namespace paludis
const std::tr1::shared_ptr<const PackageID> &,
const std::tr1::shared_ptr<const Repository> &) const;
- void _resolve_dependencies();
+ void _resolve_decide_with_dependencies();
void _resolve_destinations();
void _resolve_arrows();
void _resolve_order();
diff --git a/paludis/resolver/resolver_TEST_suggestions.cc b/paludis/resolver/resolver_TEST_suggestions.cc
new file mode 100644
index 0000000..639d180
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_suggestions.cc
@@ -0,0 +1,325 @@
+/* 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 <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 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 &)
+ {
+ 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)
+ {
+ 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;
+ }
+ }
+ };
+}
+
+namespace test_cases
+{
+ struct TestSuggestionThenDependency : ResolverSuggestionsTestCase
+ {
+ TestSuggestionThenDependency() : ResolverSuggestionsTestCase("suggestion then dependency") { }
+
+ void run()
+ {
+ std::tr1::shared_ptr<const ResolutionLists> resolutions(get_resolutions("suggestion-then-dependency/target"));
+
+ {
+ TestMessageSuffix s("errors");
+ check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ .finished()
+ );
+ }
+
+ {
+ TestMessageSuffix s("ordered");
+ check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ .qpn(QualifiedPackageName("suggestion-then-dependency/a-suggested-dep"))
+ .qpn(QualifiedPackageName("suggestion-then-dependency/hard-dep"))
+ .qpn(QualifiedPackageName("suggestion-then-dependency/target"))
+ .finished()
+ );
+ }
+
+ {
+ TestMessageSuffix s("untaken");
+ check_resolution_list(resolutions->untaken(), ResolutionListChecks()
+ .finished()
+ );
+ }
+ }
+ } test_suggestion_then_dependency;
+}
+
diff --git a/paludis/resolver/resolver_TEST_suggestions_cleanup.sh b/paludis/resolver/resolver_TEST_suggestions_cleanup.sh
new file mode 100755
index 0000000..449f710
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_suggestions_cleanup.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d resolver_TEST_suggestions_dir ] ; then
+ rm -fr resolver_TEST_suggestions_dir
+else
+ true
+fi
+
diff --git a/paludis/resolver/resolver_TEST_suggestions_setup.sh b/paludis/resolver/resolver_TEST_suggestions_setup.sh
new file mode 100755
index 0000000..d01ef46
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_suggestions_setup.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir resolver_TEST_suggestions_dir || exit 1
+cd resolver_TEST_suggestions_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
+
+# suggestion-then-dependency
+echo 'suggestion-then-dependency' > metadata/categories.conf
+
+mkdir -p 'packages/suggestion-then-dependency/target'
+cat <<END > packages/suggestion-then-dependency/target/target-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="
+ ( build,required: suggestion-then-dependency/hard-dep )
+ ( post,suggested: suggestion-then-dependency/a-suggested-dep )
+ "
+END
+
+mkdir -p 'packages/suggestion-then-dependency/hard-dep'
+cat <<END > packages/suggestion-then-dependency/hard-dep/hard-dep-1.exheres-0
+SUMMARY="hard dep"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="
+ build,required: suggestion-then-dependency/a-suggested-dep
+ "
+END
+
+mkdir -p 'packages/suggestion-then-dependency/a-suggested-dep'
+cat <<END > packages/suggestion-then-dependency/a-suggested-dep/a-suggested-dep-1.exheres-0
+SUMMARY="suggested dep"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES=""
+END
+
+cd ..
+