diff --git a/cabal-install/cabal-install.cabal b/cabal-install/cabal-install.cabal
index 321b025c91356068b2a6bb29d48170cff1f9cdff..583a79b35bd00c5334c4f1cf84a718a39d63fd9a 100644
--- a/cabal-install/cabal-install.cabal
+++ b/cabal-install/cabal-install.cabal
@@ -180,6 +180,7 @@ Test-Suite unit-tests
   other-modules:
     UnitTests.Distribution.Client.Targets
     UnitTests.Distribution.Client.Dependency.Modular.PSQ
+    UnitTests.Distribution.Client.Dependency.Modular.Solver
     UnitTests.Distribution.Client.Sandbox
     UnitTests.Distribution.Client.UserConfig
   build-depends:
diff --git a/cabal-install/tests/UnitTests.hs b/cabal-install/tests/UnitTests.hs
index f457d266d4f4928b23b6d99082ada062be872b87..28ee60fe553488987981d6d390e64df929e55bd1 100644
--- a/cabal-install/tests/UnitTests.hs
+++ b/cabal-install/tests/UnitTests.hs
@@ -2,11 +2,13 @@ module Main
        where
 
 import Test.Tasty
+import Test.Tasty.Options
 
 import qualified UnitTests.Distribution.Client.Sandbox
 import qualified UnitTests.Distribution.Client.UserConfig
 import qualified UnitTests.Distribution.Client.Targets
 import qualified UnitTests.Distribution.Client.Dependency.Modular.PSQ
+import qualified UnitTests.Distribution.Client.Dependency.Modular.Solver
 
 tests :: TestTree
 tests = testGroup "Unit Tests" [
@@ -18,7 +20,17 @@ tests = testGroup "Unit Tests" [
        UnitTests.Distribution.Client.Targets.tests
   ,testGroup "UnitTests.Distribution.Client.Dependency.Modular.PSQ"
         UnitTests.Distribution.Client.Dependency.Modular.PSQ.tests
+  ,testGroup "UnitTests.Distribution.Client.Dependency.Modular.Solver"
+        UnitTests.Distribution.Client.Dependency.Modular.Solver.tests
+  ]
+
+-- Extra options for running the test suite
+extraOptions :: [OptionDescription]
+extraOptions = concat [
+    UnitTests.Distribution.Client.Dependency.Modular.Solver.options
   ]
 
 main :: IO ()
-main = defaultMain tests
+main = defaultMainWithIngredients
+         (includingOptions extraOptions : defaultIngredients)
+         tests
diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/Solver.hs b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/Solver.hs
new file mode 100644
index 0000000000000000000000000000000000000000..b82d6ff29fc144e678eb5630aab91dff90a0c3e0
--- /dev/null
+++ b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/Solver.hs
@@ -0,0 +1,506 @@
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE CPP #-}
+module UnitTests.Distribution.Client.Dependency.Modular.Solver (tests, options) where
+
+-- base
+import Control.Monad
+import Data.Maybe (catMaybes, isNothing)
+import Data.Either (partitionEithers)
+import Data.Typeable
+import Data.Version
+import qualified Data.Map as Map
+
+#if !MIN_VERSION_base(4,8,0)
+import Data.Monoid
+#endif
+
+-- test-framework
+import Test.Tasty as TF
+import Test.Tasty.HUnit (testCase, assertEqual, assertBool)
+import Test.Tasty.Options
+
+-- Cabal
+import qualified Distribution.Compiler             as C
+import qualified Distribution.InstalledPackageInfo as C
+import qualified Distribution.Package              as C hiding (HasInstalledPackageId(..))
+import qualified Distribution.PackageDescription   as C
+import qualified Distribution.Simple.PackageIndex  as C.PackageIndex
+import qualified Distribution.System               as C
+import qualified Distribution.Version              as C
+
+-- cabal-install
+import Distribution.Client.Dependency
+import Distribution.Client.Dependency.Types
+import Distribution.Client.Types
+import qualified Distribution.Client.InstallPlan  as CI.InstallPlan
+import qualified Distribution.Client.PackageIndex as CI.PackageIndex
+
+tests :: [TF.TestTree]
+tests = [
+      testGroup "Simple dependencies" [
+          runTest $         mkTest db1 "alreadyInstalled"   ["A"]      (Just [])
+        , runTest $         mkTest db1 "installLatest"      ["B"]      (Just [("B", 2)])
+        , runTest $         mkTest db1 "simpleDep1"         ["C"]      (Just [("B", 1), ("C", 1)])
+        , runTest $         mkTest db1 "simpleDep2"         ["D"]      (Just [("B", 2), ("D", 1)])
+        , runTest $         mkTest db1 "failTwoVersions"    ["C", "D"] Nothing
+        , runTest $ indep $ mkTest db1 "indepTwoVersions"   ["C", "D"] (Just [("B", 1), ("B", 2), ("C", 1), ("D", 1)])
+        , runTest $ indep $ mkTest db1 "aliasWhenPossible1" ["C", "E"] (Just [("B", 1), ("C", 1), ("E", 1)])
+        , runTest $ indep $ mkTest db1 "aliasWhenPossible2" ["D", "E"] (Just [("B", 2), ("D", 1), ("E", 1)])
+        , runTest $ indep $ mkTest db2 "aliasWhenPossible3" ["C", "D"] (Just [("A", 1), ("A", 2), ("B", 1), ("B", 2), ("C", 1), ("D", 1)])
+        , runTest $         mkTest db1 "buildDepAgainstOld" ["F"]      (Just [("B", 1), ("E", 1), ("F", 1)])
+        , runTest $         mkTest db1 "buildDepAgainstNew" ["G"]      (Just [("B", 2), ("E", 1), ("G", 1)])
+        , runTest $ indep $ mkTest db1 "multipleInstances"  ["F", "G"] Nothing
+        ]
+    , testGroup "Flagged dependencies" [
+          runTest $         mkTest db3 "forceFlagOn"  ["C"]      (Just [("A", 1), ("B", 1), ("C", 1)])
+        , runTest $         mkTest db3 "forceFlagOff" ["D"]      (Just [("A", 2), ("B", 1), ("D", 1)])
+        , runTest $ indep $ mkTest db3 "linkFlags1"   ["C", "D"] Nothing
+        , runTest $ indep $ mkTest db4 "linkFlags2"   ["C", "D"] Nothing
+        ]
+    , testGroup "Stanzas" [
+          runTest $         mkTest db5 "simpleTest1" ["C"]      (Just [("A", 2), ("C", 1)])
+        , runTest $         mkTest db5 "simpleTest2" ["D"]      Nothing
+        , runTest $         mkTest db5 "simpleTest3" ["E"]      (Just [("A", 1), ("E", 1)])
+        , runTest $         mkTest db5 "simpleTest4" ["F"]      Nothing -- TODO
+        , runTest $         mkTest db5 "simpleTest5" ["G"]      (Just [("A", 2), ("G", 1)])
+        , runTest $         mkTest db5 "simpleTest6" ["E", "G"] Nothing
+        , runTest $ indep $ mkTest db5 "simpleTest7" ["E", "G"] (Just [("A", 1), ("A", 2), ("E", 1), ("G", 1)])
+        , runTest $         mkTest db6 "depsWithTests1" ["C"]      (Just [("A", 1), ("B", 1), ("C", 1)])
+        , runTest $ indep $ mkTest db6 "depsWithTests2" ["C", "D"] (Just [("A", 1), ("B", 1), ("C", 1), ("D", 1)])
+        ]
+    ]
+  where
+    indep test = test { testIndepGoals = True }
+
+{-------------------------------------------------------------------------------
+  Solver tests
+-------------------------------------------------------------------------------}
+
+data SolverTest = SolverTest {
+    testLabel      :: String
+  , testTargets    :: [String]
+  , testResult     :: Maybe [(String, Int)]
+  , testIndepGoals :: Bool
+  , testDb         :: ExampleDb
+  }
+
+mkTest :: ExampleDb
+       -> String
+       -> [String]
+       -> Maybe [(String, Int)]
+       -> SolverTest
+mkTest db label targets result = SolverTest {
+    testLabel      = label
+  , testTargets    = targets
+  , testResult     = result
+  , testIndepGoals = False
+  , testDb         = db
+  }
+
+runTest :: SolverTest -> TF.TestTree
+runTest SolverTest{..} = askOption $ \(OptionShowSolverLog showSolverLog) ->
+    testCase testLabel $ do
+      let (_msgs, result) = exResolve testDb testTargets testIndepGoals
+      when showSolverLog $ mapM_ putStrLn _msgs
+      case result of
+        Left  err  -> assertBool ("Unexpected error:\n" ++ err) (isNothing testResult)
+        Right plan -> assertEqual "" testResult (Just (extractInstallPlan plan))
+
+{-------------------------------------------------------------------------------
+  Specific example database for the tests
+-------------------------------------------------------------------------------}
+
+db1 :: ExampleDb
+db1 =
+    let a = ExInst "A" 1 "A-1" []
+    in [ Left a
+       , Right $ ExAv "B" 1 [ExAny "A"]
+       , Right $ ExAv "B" 2 [ExAny "A"]
+       , Right $ ExAv "C" 1 [ExFix "B" 1]
+       , Right $ ExAv "D" 1 [ExFix "B" 2]
+       , Right $ ExAv "E" 1 [ExAny "B"]
+       , Right $ ExAv "F" 1 [ExFix "B" 1, ExAny "E"]
+       , Right $ ExAv "G" 1 [ExFix "B" 2, ExAny "E"]
+       , Right $ ExAv "Z" 1 []
+       ]
+
+-- In this example, we _can_ install C and D as independent goals, but we have
+-- to pick two diferent versions for B (arbitrarily)
+db2 :: ExampleDb
+db2 = [
+    Right $ ExAv "A" 1 []
+  , Right $ ExAv "A" 2 []
+  , Right $ ExAv "B" 1 [ExAny "A"]
+  , Right $ ExAv "B" 2 [ExAny "A"]
+  , Right $ ExAv "C" 1 [ExAny "B", ExFix "A" 1]
+  , Right $ ExAv "D" 1 [ExAny "B", ExFix "A" 2]
+  ]
+
+db3 :: ExampleDb
+db3 = [
+     Right $ ExAv "A" 1 []
+   , Right $ ExAv "A" 2 []
+   , Right $ ExAv "B" 1 [ExFlag "flagB" [ExFix "A" 1] [ExFix "A" 2]]
+   , Right $ ExAv "C" 1 [ExFix "A" 1, ExAny "B"]
+   , Right $ ExAv "D" 1 [ExFix "A" 2, ExAny "B"]
+   ]
+
+-- | Like exampleDb2, but the flag picks a different package rather than a
+-- different package version
+--
+-- In exampleDb2 we cannot install C and D as independent goals because:
+--
+-- * The multiple instance restriction says C and D _must_ share B
+-- * Since C relies on A.1, C needs B to be compiled with flagB on
+-- * Since D relies on A.2, D needs B to be compiled with flagsB off
+-- * Hence C and D have incompatible requirements on B's flags.
+--
+-- However, _even_ if we don't check explicitly that we pick the same flag
+-- assignment for 0.B and 1.B, we will still detect the problem because
+-- 0.B depends on 0.A-1, 1.B depends on 1.A-2, hence we cannot link 0.A to
+-- 1.B and therefore we cannot link 0.B to 1.B.
+--
+-- In exampleDb3 the situation however is trickier. We again cannot install
+-- packages C and D as independent goals because:
+--
+-- * As above, the multiple instance restriction says that C and D _must_ share B
+-- * Since C relies on Ax-2, it requires B to be compiled with flagB off
+-- * Since D relies on Ay-2, it requires B to be compiled with flagB on
+-- * Hence C and D have incompatible requirements on B's flags.
+--
+-- But now this requirement is more indirect. If we only check dependencies
+-- we don't see the problem:
+--
+-- * We link 0.B to 1.B
+-- * 0.B relies on Ay.1
+-- * 1.B relies on Ax.1
+--
+-- We will insist that 0.Ay will be linked to 1.Ay, and 0.Ax to 1.A, but since
+-- we only ever assign to one of these, these constraints are never broken.
+db4 :: ExampleDb
+db4 = [
+     Right $ ExAv "Ax" 1 []
+   , Right $ ExAv "Ax" 2 []
+   , Right $ ExAv "Ay" 1 []
+   , Right $ ExAv "Ay" 2 []
+   , Right $ ExAv "B"  1 [ExFlag "flagB" [ExFix "Ax" 1] [ExFix "Ay" 1]]
+   , Right $ ExAv "C"  1 [ExFix "Ax" 2, ExAny "B"]
+   , Right $ ExAv "D"  1 [ExFix "Ay" 2, ExAny "B"]
+   ]
+
+-- | Some tests involving testsuites
+--
+-- Note that in this test framework test suites are always enabled; if you
+-- want to test without test suites just set up a test database without
+-- test suites.
+--
+-- * C depends on A (through its test suite)
+-- * D depends on B-2 (through its test suite), but B-2 is unavailable
+-- * E depends on A-1 directly and on A through its test suite. We prefer
+--     to use A-1 for the test suite in this case.
+-- * F depends on A-1 directly and on A-2 through its test suite. In this
+--     case we currently fail to install F, although strictly speaking
+--     test suites should be considered independent goals.
+-- * G is like E, but for version A-2. This means that if we cannot install
+--     E and G together, unless we regard them as independent goals.
+db5 :: ExampleDb
+db5 = [
+    Right $ ExAv "A" 1 []
+  , Right $ ExAv "A" 2 []
+  , Right $ ExAv "B" 1 []
+  , Right $ ExAv "C" 1 [ExTest "testC" [ExAny "A"]]
+  , Right $ ExAv "D" 1 [ExTest "testD" [ExFix "B" 2]]
+  , Right $ ExAv "E" 1 [ExFix "A" 1, ExTest "testE" [ExAny "A"]]
+  , Right $ ExAv "F" 1 [ExFix "A" 1, ExTest "testF" [ExFix "A" 2]]
+  , Right $ ExAv "G" 1 [ExFix "A" 2, ExTest "testG" [ExAny "A"]]
+  ]
+
+-- Now the _dependencies_ have test suites
+--
+-- * Installing C is a simple example. C wants version 1 of A, but depends on
+--   B, and B's testsuite depends on an any version of A. In this case we prefer
+--   to link (if we don't regard test suites as independent goals then of course
+--   linking here doesn't even come into it).
+-- * Installing [C, D] means that we prefer to link B -- depending on how we
+--   set things up, this means that we should also link their test suites.
+db6 :: ExampleDb
+db6 = [
+    Right $ ExAv "A" 1 []
+  , Right $ ExAv "A" 2 []
+  , Right $ ExAv "B" 1 [ExTest "testA" [ExAny "A"]]
+  , Right $ ExAv "C" 1 [ExFix "A" 1, ExAny "B"]
+  , Right $ ExAv "D" 1 [ExAny "B"]
+  ]
+
+{-------------------------------------------------------------------------------
+  Example package database DSL
+
+  In order to be able to set simple examples up quickly, we define a very
+  simple version of the package database here explicitly designed for use in
+  tests.
+
+  The design of `ExampleDb` takes the perspective of the solver, not the
+  perspective of the package DB. This makes it easier to set up tests for
+  various parts of the solver, but makes the mapping somewhat awkward,  because
+  it means we first map from "solver perspective" `ExampleDb` to the package
+  database format, and then the modular solver internally in `IndexConversion`
+  maps this back to the solver specific data structures.
+
+  IMPLEMENTATION NOTES
+  --------------------
+
+  TODO: Perhaps these should be made comments of the corresponding data type
+  definitions. For now these are just my own conclusions and may be wrong.
+
+  * The difference between `GenericPackageDescription` and `PackageDescription`
+    is that `PackageDescription` describes a particular _configuration_ of a
+    package (for instance, see documentation for `checkPackage`). A
+    `GenericPackageDescription` can be returned into a `PackageDescription` in
+    two ways:
+
+      a. `finalizePackageDescription` does the proper translation, by taking
+         into account the platform, available dependencies, etc. and picks a
+         flag assignment (or gives an error if no flag assignment can be found)
+      b. `flattenPackageDescription` ignores flag assignment and just joins all
+         components together.
+
+    The slightly odd thing is that a `GenericPackageDescription` contains a
+    `PackageDescription` as a field; both of the above functions do the same
+    thing: they take the embedded `PackageDescription` as a basis for the result
+    value, but override `library`, `executables`, `testSuites`, `benchmarks`
+    and `buildDepends`.
+  * The `condTreeComponents` fields of a `CondTree` is a list of triples
+    `(condition, then-branch, else-branch)`, where the `else-branch` is
+    optional.
+-------------------------------------------------------------------------------}
+
+type ExamplePkgName    = String
+type ExamplePkgVersion = Int
+type ExamplePkgHash    = String  -- for example "installed" packages
+type ExampleFlagName   = String
+type ExampleTestName   = String
+
+data ExampleDependency =
+    -- | Simple dependency on any version
+    ExAny ExamplePkgName
+
+    -- | Simple dependency on a fixed version
+  | ExFix ExamplePkgName ExamplePkgVersion
+
+    -- | Dependencies indexed by a flag
+  | ExFlag ExampleFlagName [ExampleDependency] [ExampleDependency]
+
+    -- | Dependency if tests are enabled
+  | ExTest ExampleTestName [ExampleDependency]
+
+data ExampleAvailable = ExAv {
+    exAvName    :: ExamplePkgName
+  , exAvVersion :: ExamplePkgVersion
+  , exAvDeps    :: [ExampleDependency]
+  }
+
+data ExampleInstalled = ExInst {
+    exInstName         :: ExamplePkgName
+  , exInstVersion      :: ExamplePkgVersion
+  , exInstHash         :: ExamplePkgHash
+  , exInstBuildAgainst :: [ExampleInstalled]
+  }
+
+type ExampleDb = [Either ExampleInstalled ExampleAvailable]
+
+type DependencyTree a = C.CondTree C.ConfVar [C.Dependency] a
+
+exDbPkgs :: ExampleDb -> [ExamplePkgName]
+exDbPkgs = map (either exInstName exAvName)
+
+exAvSrcPkg :: ExampleAvailable -> SourcePackage
+exAvSrcPkg ex =
+    let (libraryDeps, testSuites) = splitTopLevel (exAvDeps ex)
+    in SourcePackage {
+           packageInfoId        = exAvPkgId ex
+         , packageSource        = LocalTarballPackage "<<path>>"
+         , packageDescrOverride = Nothing
+         , packageDescription   = C.GenericPackageDescription{
+               C.packageDescription = C.emptyPackageDescription {
+                   C.package      = exAvPkgId ex
+                 , C.library      = error "not yet configured: library"
+                 , C.executables  = error "not yet configured: executables"
+                 , C.testSuites   = error "not yet configured: testSuites"
+                 , C.benchmarks   = error "not yet configured: benchmarks"
+                 , C.buildDepends = error "not yet configured: buildDepends"
+                 }
+             , C.genPackageFlags = concatMap extractFlags (exAvDeps ex)
+             , C.condLibrary     = Just $ mkCondTree libraryDeps
+             , C.condExecutables = []
+             , C.condTestSuites  = map (\(t, deps) -> (t, mkCondTree deps)) testSuites
+             , C.condBenchmarks  = []
+             }
+         }
+  where
+    splitTopLevel :: [ExampleDependency]
+                  -> ( [ExampleDependency]
+                     , [(ExampleTestName, [ExampleDependency])]
+                     )
+    splitTopLevel []                = ([], [])
+    splitTopLevel (ExTest t a:deps) = let (other, testSuites) = splitTopLevel deps
+                                      in (other, (t, a):testSuites)
+    splitTopLevel (dep:deps)        = let (other, testSuites) = splitTopLevel deps
+                                      in (dep:other, testSuites)
+
+    extractFlags :: ExampleDependency -> [C.Flag]
+    extractFlags (ExAny _)      = []
+    extractFlags (ExFix _ _)    = []
+    extractFlags (ExFlag f a b) = C.MkFlag {
+                                      C.flagName        = C.FlagName f
+                                    , C.flagDescription = ""
+                                    , C.flagDefault     = False
+                                    , C.flagManual      = False
+                                    }
+                                : concatMap extractFlags (a ++ b)
+    extractFlags (ExTest _ a)   = concatMap extractFlags a
+
+    mkCondTree :: Monoid a => [ExampleDependency] -> DependencyTree a
+    mkCondTree deps =
+      let (directDeps, flaggedDeps) = splitDeps deps
+      in C.CondNode {
+             C.condTreeData        = mempty -- irrelevant to the solver
+           , C.condTreeConstraints = map mkDirect  directDeps
+           , C.condTreeComponents  = map mkFlagged flaggedDeps
+           }
+
+    mkDirect :: (ExamplePkgName, Maybe ExamplePkgVersion) -> C.Dependency
+    mkDirect (dep, Nothing) = C.Dependency (C.PackageName dep) C.anyVersion
+    mkDirect (dep, Just n)  = C.Dependency (C.PackageName dep) (C.thisVersion v)
+      where
+        v = Version [n, 0, 0] []
+
+    mkFlagged :: Monoid a
+              => (ExampleFlagName, [ExampleDependency], [ExampleDependency])
+              -> (C.Condition C.ConfVar, DependencyTree a, Maybe (DependencyTree a))
+    mkFlagged (f, a, b) = ( C.Var (C.Flag (C.FlagName f))
+                          , mkCondTree a
+                          , Just (mkCondTree b)
+                          )
+
+    splitDeps :: [ExampleDependency]
+              -> ( [(ExamplePkgName, Maybe Int)]
+                 , [(ExampleFlagName, [ExampleDependency], [ExampleDependency])]
+                 )
+    splitDeps [] =
+      ([], [])
+    splitDeps (ExAny p:deps) =
+      let (directDeps, flaggedDeps) = splitDeps deps
+      in ((p, Nothing):directDeps, flaggedDeps)
+    splitDeps (ExFix p v:deps) =
+      let (directDeps, flaggedDeps) = splitDeps deps
+      in ((p, Just v):directDeps, flaggedDeps)
+    splitDeps (ExFlag f a b:deps) =
+      let (directDeps, flaggedDeps) = splitDeps deps
+      in (directDeps, (f, a, b):flaggedDeps)
+    splitDeps (ExTest _ _:_) =
+      error "Unexpected nested test"
+
+exAvPkgId :: ExampleAvailable -> C.PackageIdentifier
+exAvPkgId ex = C.PackageIdentifier {
+      pkgName    = C.PackageName (exAvName ex)
+    , pkgVersion = Version [exAvVersion ex, 0, 0] []
+    }
+
+exInstInfo :: ExampleInstalled -> C.InstalledPackageInfo
+exInstInfo ex = C.emptyInstalledPackageInfo {
+      C.installedPackageId = C.InstalledPackageId (exInstHash ex)
+    , C.sourcePackageId    = exInstPkgId ex
+    , C.packageKey         = exInstKey ex
+    , C.depends            = map (C.InstalledPackageId . exInstHash)
+                                 (exInstBuildAgainst ex)
+    }
+
+exInstPkgId :: ExampleInstalled -> C.PackageIdentifier
+exInstPkgId ex = C.PackageIdentifier {
+      pkgName    = C.PackageName (exInstName ex)
+    , pkgVersion = Version [exInstVersion ex, 0, 0] []
+    }
+
+exInstKey :: ExampleInstalled -> C.PackageKey
+exInstKey ex =
+    C.mkPackageKey True
+                   (exInstPkgId ex)
+                   (map exInstKey (exInstBuildAgainst ex))
+                   []
+
+exAvIdx :: [ExampleAvailable] -> CI.PackageIndex.PackageIndex SourcePackage
+exAvIdx = CI.PackageIndex.fromList . map exAvSrcPkg
+
+exInstIdx :: [ExampleInstalled] -> C.PackageIndex.InstalledPackageIndex
+exInstIdx = C.PackageIndex.fromList . map exInstInfo
+
+exResolve :: ExampleDb
+          -> [ExamplePkgName]
+          -> Bool
+          -> ([String], Either String CI.InstallPlan.InstallPlan)
+exResolve db targets indepGoals = runProgress $
+    resolveDependencies C.buildPlatform
+                        (C.unknownCompilerInfo C.buildCompilerId C.NoAbiTag)
+                        Modular
+                        params
+  where
+    (inst, avai) = partitionEithers db
+    instIdx      = exInstIdx inst
+    avaiIdx      = SourcePackageDb {
+                       packageIndex       = exAvIdx avai
+                     , packagePreferences = Map.empty
+                     }
+    enableTests  = map (\p -> PackageConstraintStanzas (C.PackageName p) [TestStanzas])
+                       (exDbPkgs db)
+    targets'     = map (\p -> NamedPackage (C.PackageName p) []) targets
+    params       = addConstraints enableTests
+                 $ (standardInstallPolicy instIdx avaiIdx targets') {
+                       depResolverIndependentGoals = indepGoals
+                     }
+
+extractInstallPlan :: CI.InstallPlan.InstallPlan
+                   -> [(ExamplePkgName, ExamplePkgVersion)]
+extractInstallPlan = catMaybes . map confPkg . CI.InstallPlan.toList
+  where
+    confPkg :: CI.InstallPlan.PlanPackage -> Maybe (String, Int)
+    confPkg (CI.InstallPlan.Configured pkg) = Just $ srcPkg pkg
+    confPkg _                               = Nothing
+
+    srcPkg :: ConfiguredPackage -> (String, Int)
+    srcPkg (ConfiguredPackage pkg _flags _stanzas _deps) =
+      let C.PackageIdentifier (C.PackageName p) (Version (n:_) _) = packageInfoId pkg
+      in (p, n)
+
+{-------------------------------------------------------------------------------
+  Auxiliary
+-------------------------------------------------------------------------------}
+
+-- | Run Progress computation
+--
+-- Like `runLog`, but for the more general `Progress` type.
+runProgress :: Progress step e a -> ([step], Either e a)
+runProgress = go
+  where
+    go (Step s p) = let (ss, result) = go p in (s:ss, result)
+    go (Fail e)   = ([], Left e)
+    go (Done a)   = ([], Right a)
+
+{-------------------------------------------------------------------------------
+  Test options
+-------------------------------------------------------------------------------}
+
+options :: [OptionDescription]
+options = [
+    Option (Proxy :: Proxy OptionShowSolverLog)
+  ]
+
+newtype OptionShowSolverLog = OptionShowSolverLog Bool
+  deriving Typeable
+
+instance IsOption OptionShowSolverLog where
+  defaultValue   = OptionShowSolverLog False
+  parseValue     = fmap OptionShowSolverLog . safeRead
+  optionName     = return "show-solver-log"
+  optionHelp     = return "Show full log from the solver"
+  optionCLParser = flagCLParser Nothing (OptionShowSolverLog True)