diff --git a/cabal-testsuite/PackageTests/CustomDep/cabal.test.hs b/cabal-testsuite/PackageTests/CustomDep/cabal.test.hs
index b1c3aa9880265424b5957f294feafe387158c4cd..9058afe19c046940727093ae17c6f01aa9313f47 100644
--- a/cabal-testsuite/PackageTests/CustomDep/cabal.test.hs
+++ b/cabal-testsuite/PackageTests/CustomDep/cabal.test.hs
@@ -1,7 +1,5 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
-    -- NB: This variant seems to use the bootstrapped Cabal?
-    skipUnless "no Cabal for GHC" =<< hasCabalForGhc
     -- implicit setup-depends conflict with GHC >= 8.2; c.f. #415
     skipUnlessGhcVersion "< 8.2"
     -- This test depends heavily on what packages are in the global
diff --git a/cabal-testsuite/PackageTests/CustomPlain/setup.test.hs b/cabal-testsuite/PackageTests/CustomPlain/setup.test.hs
index 2b4a27b138876406cfeac1092c836e44acb97eeb..abf668397b80fd8c0a09c2e7cac8b7a09c43ce2a 100644
--- a/cabal-testsuite/PackageTests/CustomPlain/setup.test.hs
+++ b/cabal-testsuite/PackageTests/CustomPlain/setup.test.hs
@@ -1,5 +1,4 @@
 import Test.Cabal.Prelude
 main = setupTest $ do
-    skipUnless "no Cabal for GHC" =<< hasCabalForGhc
     setup' "configure" [] >>= assertOutputContains "ThisIsCustomYeah"
     setup' "build"     [] >>= assertOutputContains "ThisIsCustomYeah"
diff --git a/cabal-testsuite/PackageTests/CustomPreProcess/cabal.test.hs b/cabal-testsuite/PackageTests/CustomPreProcess/cabal.test.hs
index 93588d88c3f9b9efca7be9632d51d8325892c992..3c20b50a160021c30ed71d4abca9ab509b7effbc 100644
--- a/cabal-testsuite/PackageTests/CustomPreProcess/cabal.test.hs
+++ b/cabal-testsuite/PackageTests/CustomPreProcess/cabal.test.hs
@@ -1,8 +1,6 @@
 import Test.Cabal.Prelude
 -- Test internal custom preprocessor
 main = cabalTest $ do
-    skipUnless "no Cabal for GHC" =<< hasCabalForGhc
-
     -- old Cabal's ./Setup.hs output is difficult to normalise
     recordMode DoNotRecord $
         cabal "v2-build" []
diff --git a/cabal-testsuite/PackageTests/CustomPreProcess/setup.test.hs b/cabal-testsuite/PackageTests/CustomPreProcess/setup.test.hs
index 2dab697b8d401e07a402e7d73a9ab698fbf39e2f..b3d1f3c0a46bfcbec0aa0d844d38f7d2b4ef64f3 100644
--- a/cabal-testsuite/PackageTests/CustomPreProcess/setup.test.hs
+++ b/cabal-testsuite/PackageTests/CustomPreProcess/setup.test.hs
@@ -1,7 +1,6 @@
 import Test.Cabal.Prelude
 -- Test internal custom preprocessor
 main = setupTest $ do
-    skipUnless "no Cabal for GHC" =<< hasCabalForGhc
     setup_build []
     runExe' "hello-world" []
         >>= assertOutputContains "hello from A"
diff --git a/cabal-testsuite/PackageTests/CustomTestCoverage/setup.test.hs b/cabal-testsuite/PackageTests/CustomTestCoverage/setup.test.hs
index 7f40ed74bc87297dead14238a28b7e30be7eda39..86cc6a258ab3f331f25406202b194be268d6f7f4 100644
--- a/cabal-testsuite/PackageTests/CustomTestCoverage/setup.test.hs
+++ b/cabal-testsuite/PackageTests/CustomTestCoverage/setup.test.hs
@@ -1,7 +1,7 @@
 import Test.Cabal.Prelude
 main = setupTest $ do
+  skipIfGhcVersion "== 7.8.4"
   recordMode DoNotRecord $ do
-    skipUnless "no Cabal for GHC" =<< hasCabalForGhc
     setup' "configure" ["--enable-tests", "--enable-coverage"] >>= assertOutputContains "ThisIsCustomYeah"
     setup' "build"     []
     setup' "test"      [] >>= assertOutputContains "Package coverage report written to"
diff --git a/cabal-testsuite/PackageTests/DuplicateModuleName/setup.test.hs b/cabal-testsuite/PackageTests/DuplicateModuleName/setup.test.hs
index 3739c793e8fecddd39639186bf73fa0d49cf08f3..005578ce184a43affabdfacd153cbccdcaedaf01 100644
--- a/cabal-testsuite/PackageTests/DuplicateModuleName/setup.test.hs
+++ b/cabal-testsuite/PackageTests/DuplicateModuleName/setup.test.hs
@@ -2,7 +2,7 @@ import Test.Cabal.Prelude
 -- Test that if two components have the same module name, they do not
 -- clobber each other.
 main = setupAndCabalTest $ do
-    skipUnless "no Cabal for GHC" =<< hasCabalForGhc -- use of library test suite
+    skipIfAllCabalVersion "< 2.2"
     setup_build ["--enable-tests"]
     r1 <- fails $ setup' "test" ["foo"]
     assertOutputContains "test B" r1
diff --git a/cabal-testsuite/PackageTests/MultiRepl/CabalTooOld/cabal.out b/cabal-testsuite/PackageTests/MultiRepl/CabalTooOld/cabal.out
index f2253c67190d758759fc0060e620634d66e68968..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/cabal-testsuite/PackageTests/MultiRepl/CabalTooOld/cabal.out
+++ b/cabal-testsuite/PackageTests/MultiRepl/CabalTooOld/cabal.out
@@ -1,11 +0,0 @@
-# cabal v2-update
-Downloading the latest package list from test-local-repo
-# cabal v2-repl
-Resolving dependencies...
-Error: [Cabal-7107]
-Could not resolve dependencies:
-[__0] trying: pkg-a-0 (user goal)
-[__1] next goal: pkg-a:setup.Cabal (dependency of pkg-a)
-[__1] rejecting: pkg-a:setup.Cabal-<VERSION>/installed-<HASH>, pkg-a:setup.Cabal-3.8.0.0 (constraint from --enable-multi-repl requires >=3.11)
-[__1] fail (backjumping, conflict set: pkg-a, pkg-a:setup.Cabal)
-After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: pkg-a:setup.Cabal (3), pkg-a (2)
diff --git a/cabal-testsuite/PackageTests/MultiRepl/CabalTooOld/cabal.test.hs b/cabal-testsuite/PackageTests/MultiRepl/CabalTooOld/cabal.test.hs
index 978b52e72ecf89e1198c288750b5e089d2d4c766..2f4faa0c24de9bd158fa244d7960b4c05ef412cb 100644
--- a/cabal-testsuite/PackageTests/MultiRepl/CabalTooOld/cabal.test.hs
+++ b/cabal-testsuite/PackageTests/MultiRepl/CabalTooOld/cabal.test.hs
@@ -1,5 +1,8 @@
 import Test.Cabal.Prelude
 
-main = cabalTest $ withRepo "repo" $ do
+main = cabalTest $ recordMode DoNotRecord . withRepo "repo" $ do
+    -- For the multi-repl command
     skipUnlessGhcVersion ">= 9.4"
-    void $ fails $ cabalWithStdin "v2-repl" ["--keep-temp-files","--enable-multi-repl","pkg-a", "pkg-b"] ""
+    skipUnlessAnyCabalVersion "< 3.11"
+    res <- fails $ cabalWithStdin "v2-repl" ["--keep-temp-files","--enable-multi-repl","pkg-a", "pkg-b"] ""
+    assertOutputContains "constraint from --enable-multi-repl requires >=3.11" res
diff --git a/cabal-testsuite/PackageTests/MultiRepl/EnabledBadClosure/cabal.out b/cabal-testsuite/PackageTests/MultiRepl/EnabledBadClosure/cabal.out
index e92fa0c9fbaf838d9fc7e886d8ce0b7250665c03..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/cabal-testsuite/PackageTests/MultiRepl/EnabledBadClosure/cabal.out
+++ b/cabal-testsuite/PackageTests/MultiRepl/EnabledBadClosure/cabal.out
@@ -1,9 +0,0 @@
-# cabal v2-repl
-Resolving dependencies...
-Error: [Cabal-7107]
-Could not resolve dependencies:
-[__0] trying: pkg-b-0 (user goal)
-[__1] next goal: pkg-b:setup.Cabal (dependency of pkg-b)
-[__1] rejecting: pkg-b:setup.Cabal-<VERSION>/installed-<HASH> (constraint from --enable-multi-repl requires >=3.11)
-[__1] fail (backjumping, conflict set: pkg-b, pkg-b:setup.Cabal)
-After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: pkg-b (2), pkg-b:setup.Cabal (2)
diff --git a/cabal-testsuite/PackageTests/MultiRepl/EnabledBadClosure/cabal.test.hs b/cabal-testsuite/PackageTests/MultiRepl/EnabledBadClosure/cabal.test.hs
index 2fcfe8e6533159d5219fbc2b68f976807dcb20a2..3f86e566dfa23afc24be533ff9c61146290dd7b5 100644
--- a/cabal-testsuite/PackageTests/MultiRepl/EnabledBadClosure/cabal.test.hs
+++ b/cabal-testsuite/PackageTests/MultiRepl/EnabledBadClosure/cabal.test.hs
@@ -1,9 +1,8 @@
 import Test.Cabal.Prelude
 
 main = do
-  cabalTest $ do
-    -- MP: TODO: This should query Cabal library version
-    skipIfGhcVersion ">= 9.10"
+  cabalTest $ recordMode DoNotRecord $ do
+    skipUnlessAnyCabalVersion "< 3.11"
     -- Note: only the last package is interactive.
     -- this test should load pkg-b too.
     res <- fails $ cabalWithStdin "v2-repl" ["--enable-multi-repl","pkg-c", "pkg-a"] "Quu.quu"
diff --git a/cabal-testsuite/PackageTests/PackageDB/cabal-fail-no-packagedbs.test.hs b/cabal-testsuite/PackageTests/PackageDB/cabal-fail-no-packagedbs.test.hs
index 1cc0f54d15994728ac5be179c9182e0be2127f91..5335d960ab8f6384ee5746eb78c833de2c2c89aa 100644
--- a/cabal-testsuite/PackageTests/PackageDB/cabal-fail-no-packagedbs.test.hs
+++ b/cabal-testsuite/PackageTests/PackageDB/cabal-fail-no-packagedbs.test.hs
@@ -1,6 +1,6 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
-    withPackageDb $ do
+    noCabalPackageDb . withPackageDb $ do
         withDirectory "p-no-package-dbs" $ do
             res <- fails $ cabal' "v2-build" []
             assertOutputContains "No package databases have been specified." res
diff --git a/cabal-testsuite/PackageTests/Regression/T4270/setup.test.hs b/cabal-testsuite/PackageTests/Regression/T4270/setup.test.hs
index cf3d7afbdfbc171930973c7ce0d23edd9309092d..258dcc21e16c5b11477a283694520a2175f24e15 100644
--- a/cabal-testsuite/PackageTests/Regression/T4270/setup.test.hs
+++ b/cabal-testsuite/PackageTests/Regression/T4270/setup.test.hs
@@ -3,9 +3,9 @@ import Test.Cabal.Prelude
 -- when linked dynamically
 -- See https://github.com/haskell/cabal/issues/4270
 main = setupAndCabalTest $ do
+  skipIfAllCabalVersion "< 2.2"
   skipUnless "no shared libs"   =<< hasSharedLibraries
   skipUnless "no shared Cabal"  =<< hasCabalShared
-  skipUnless "no Cabal for GHC" =<< hasCabalForGhc
   ghc <- isGhcVersion "== 8.0.2"
   osx <- isOSX
   expectBrokenIf (osx && ghc) 8028 $ do
diff --git a/cabal-testsuite/PackageTests/TestNameCollision/setup.test.hs b/cabal-testsuite/PackageTests/TestNameCollision/setup.test.hs
index 19d2fc904683c09ab8479129c408d216c7e4873e..93e8a820b30ec54a8c0bf39333f6fd29dd2dff05 100644
--- a/cabal-testsuite/PackageTests/TestNameCollision/setup.test.hs
+++ b/cabal-testsuite/PackageTests/TestNameCollision/setup.test.hs
@@ -3,7 +3,7 @@ import Test.Cabal.Prelude
 -- which is in the database, we can still use the test case (they
 -- should NOT shadow).
 main = setupAndCabalTest $ do
-    skipUnless "cabal for ghc" =<< hasCabalForGhc -- use of library test suite
+    skipIfAllCabalVersion "< 2.2"
     withPackageDb $ do
         withDirectory "parent" $ setup_install []
         withDirectory "child" $ do
diff --git a/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup-deadlock.test.hs b/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup-deadlock.test.hs
index 69529404d97847904c10f95b9bd26a7b14eff157..d9b8f3c3d15cdcfc2e0b30396e6e4e0061ae0a72 100644
--- a/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup-deadlock.test.hs
+++ b/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup-deadlock.test.hs
@@ -1,5 +1,5 @@
 import Test.Cabal.Prelude
 main = setupAndCabalTest $ do
-    skipUnless "no Cabal for GHC" =<< hasCabalForGhc
+    skipIfAllCabalVersion "< 2.2"
     setup_build ["--enable-tests"]
     fails $ setup "test" []
diff --git a/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup.test.hs b/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup.test.hs
index 1a50e4d67e4aa0393cd07d6edb54080b2b439793..42c5556cfa317161073dd815dcdf9cda6d7bdf7e 100644
--- a/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup.test.hs
+++ b/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup.test.hs
@@ -1,5 +1,5 @@
 import Test.Cabal.Prelude
 -- Test if detailed-0.9 builds correctly
 main = setupAndCabalTest $ do
-    skipUnless "no Cabal for GHC" =<< hasCabalForGhc
+    skipIfAllCabalVersion "< 1.20"
     setup_build ["--enable-tests"]
diff --git a/cabal-testsuite/README.md b/cabal-testsuite/README.md
index f217617e9327fa9cc770afc7c9a391bd4cebe7b5..afe08e499dc198f4e63ab7de324207f7b17ced7b 100644
--- a/cabal-testsuite/README.md
+++ b/cabal-testsuite/README.md
@@ -28,6 +28,31 @@ There are a few useful flags:
 * `--keep-tmp-files` can be used to keep the temporary directories that tests
   are run in.
 
+## Which Cabal library version do cabal-install tests use?
+
+By default the `cabal-install` tests will use the `Cabal` library which comes with
+the boot compiler when it needs to build a custom `Setup.hs`.
+
+This can be very confusing if you are modifying the Cabal library, writing a test
+which relies on a custom setup script and you are wondering why the test is not
+responding at all to your changes.
+
+There are some flags which allow you to instruct `cabal-install` to use a different
+`Cabal` library version.
+
+1. `--boot-cabal-lib` specifies to use the Cabal library bundled with the
+   test compiler, this is the default.
+2. `--intree-cabal-lib=<root_dir>` specifies to use Cabal and Cabal-syntax
+   from a specific directory, and `--test-tmp` indicates where to put
+   the package database they are built into.
+3. `--specific-cabal-lib=<VERSION>` specifies to use a specific Cabal
+   version from hackage (ie 3.10.2.0) and installs the package database
+   into `--test-tmp=<DIR>`
+
+The CI scripts use the `--intree-cabal-lib` option for the most part but in
+the future there should be a variety of jobs which test `cabal-install` built
+against newer `Cabal` versions but forced to interact with older `Cabal` versions.
+
 ### How to run the doctests
 
 You need to install the `doctest` tool. Make sure it's compiled with your current
@@ -173,8 +198,7 @@ and stderr.
 **How do I skip running a test in some environments?**  Use the
 `skipIf` and `skipUnless` combinators.  Useful parameters to test
 these with include `hasSharedLibraries`, `hasProfiledLibraries`,
-`hasCabalShared`, `isGhcVersion`, `isWindows`, `isLinux`, `isOSX`
-and `hasCabalForGhc`.
+`hasCabalShared`, `isGhcVersion`, `isWindows`, `isLinux`, `isOSX`.
 
 **I programmatically modified a file in my test suite, but Cabal/GHC
 doesn't seem to be picking it up.**  You need to sleep sufficiently
diff --git a/cabal-testsuite/cabal-testsuite.cabal b/cabal-testsuite/cabal-testsuite.cabal
index e99ea880d244256d637a611b5d86b90f5e32f61f..cb5a3fe605d71621e9e5c6d6ccea3ba6856f6368 100644
--- a/cabal-testsuite/cabal-testsuite.cabal
+++ b/cabal-testsuite/cabal-testsuite.cabal
@@ -104,6 +104,7 @@ executable cabal-tests
     , transformers
     -- dependencies specific to exe:cabal-tests
     , clock                 ^>= 0.7.2 || ^>=0.8
+    , directory
 
   build-tool-depends: cabal-testsuite:setup
   default-extensions: TypeOperators
diff --git a/cabal-testsuite/main/cabal-tests.hs b/cabal-testsuite/main/cabal-tests.hs
index 8f8e8ec2807eee38cf64823eff4ee06715dcaa73..b6a76ccf485b82e46f97b7f233b6b9e69ee68a91 100644
--- a/cabal-testsuite/main/cabal-tests.hs
+++ b/cabal-testsuite/main/cabal-tests.hs
@@ -11,6 +11,7 @@ import Test.Cabal.TestCode
 
 import Distribution.Verbosity        (normal, verbose, Verbosity)
 import Distribution.Simple.Utils     (getDirectoryContentsRecursive)
+import Distribution.Simple.Program
 
 import Options.Applicative
 import Control.Concurrent.MVar
@@ -26,6 +27,9 @@ import System.IO
 import System.FilePath
 import System.Exit
 import System.Process (callProcess, showCommandForUser)
+import System.Directory
+import Distribution.Pretty
+import Data.Maybe
 
 #if !MIN_VERSION_base(4,12,0)
 import Data.Monoid ((<>))
@@ -71,9 +75,22 @@ data MainArgs = MainArgs {
         mainArgVerbose :: Bool,
         mainArgQuiet   :: Bool,
         mainArgDistDir :: Maybe FilePath,
+        mainArgCabalSpec :: Maybe CabalLibSpec,
         mainCommonArgs :: CommonArgs
     }
 
+data CabalLibSpec = BootCabalLib | InTreeCabalLib FilePath FilePath | SpecificCabalLib String FilePath
+
+cabalLibSpecParser :: Parser CabalLibSpec
+cabalLibSpecParser = bootParser <|> intreeParser <|> specificParser
+  where
+    bootParser = flag' BootCabalLib (long "boot-cabal-lib")
+    intreeParser = InTreeCabalLib <$> strOption (long "intree-cabal-lib" <> metavar "ROOT")
+                                  <*> option str ( help "Test TMP" <> long "test-tmp" )
+    specificParser = SpecificCabalLib <$> strOption (long "specific-cabal-lib" <> metavar "VERSION")
+                                      <*> option str ( help "Test TMP" <> long "test-tmp" )
+
+
 -- | optparse-applicative parser for 'MainArgs'
 mainArgParser :: Parser MainArgs
 mainArgParser = MainArgs
@@ -102,8 +119,52 @@ mainArgParser = MainArgs
         ( help "Dist directory we were built with"
        <> long "builddir"
        <> metavar "DIR"))
+    <*> optional cabalLibSpecParser
     <*> commonArgParser
 
+-- Unpack and build a specific released version of Cabal and Cabal-syntax libraries
+buildCabalLibsProject :: String -> Verbosity -> Maybe FilePath -> FilePath -> IO FilePath
+buildCabalLibsProject projString verb mbGhc dir = do
+  let prog_db = userSpecifyPaths [("ghc", path) | Just path <- [mbGhc] ]  defaultProgramDb
+  (cabal, _) <- requireProgram verb (simpleProgram "cabal") prog_db
+  (ghc, _) <- requireProgram verb ghcProgram prog_db
+
+  let pv = fromMaybe (error "no ghc version") (programVersion ghc)
+  let final_package_db = dir </> "dist-newstyle" </> "packagedb" </> "ghc-" ++ prettyShow pv
+  createDirectoryIfMissing True dir
+  writeFile (dir </> "cabal.project-test") projString
+
+  runProgramInvocation verb
+    ((programInvocation cabal
+      ["--store-dir", dir </> "store"
+      , "--project-file=" ++ dir </> "cabal.project-test"
+      , "build"
+      , "-w", programPath ghc
+      , "Cabal", "Cabal-syntax"] ) { progInvokeCwd = Just dir })
+  return final_package_db
+
+
+buildCabalLibsSpecific :: String -> Verbosity -> Maybe FilePath -> FilePath -> IO FilePath
+buildCabalLibsSpecific ver verb mbGhc builddir_rel = do
+  let prog_db = userSpecifyPaths [("ghc", path) | Just path <- [mbGhc] ]  defaultProgramDb
+  (cabal, _) <- requireProgram verb (simpleProgram "cabal") prog_db
+  dir <- canonicalizePath (builddir_rel </> "specific" </> ver)
+  cgot <- doesDirectoryExist (dir </> "Cabal-" ++ ver)
+  unless cgot $
+    runProgramInvocation verb ((programInvocation cabal ["get", "Cabal-" ++ ver]) { progInvokeCwd = Just dir })
+  csgot <- doesDirectoryExist (dir </> "Cabal-syntax-" ++ ver)
+  unless csgot $
+    runProgramInvocation verb ((programInvocation cabal ["get", "Cabal-syntax-" ++ ver]) { progInvokeCwd = Just dir })
+
+  buildCabalLibsProject ("packages: Cabal-" ++ ver ++ " Cabal-syntax-" ++ ver) verb mbGhc dir
+
+
+buildCabalLibsIntree :: String -> Verbosity -> Maybe FilePath -> FilePath -> IO FilePath
+buildCabalLibsIntree root verb mbGhc builddir_rel = do
+  dir <- canonicalizePath (builddir_rel </> "intree")
+  buildCabalLibsProject ("packages: " ++ root </> "Cabal" ++ " " ++ root </> "Cabal-syntax") verb mbGhc dir
+
+
 main :: IO ()
 main = do
     -- By default, stderr is not buffered.  This isn't really necessary
@@ -115,6 +176,27 @@ main = do
     args <- execParser $ info (mainArgParser <**> helper) mempty
     let verbosity = if mainArgVerbose args then verbose else normal
 
+    mpkg_db <-
+      -- Not path to cabal-install so we're not going to run cabal-install tests so we
+      -- can skip setting up a Cabal library to use with cabal-install.
+      case argCabalInstallPath (mainCommonArgs args) of
+        Nothing -> do
+          when (isJust $ mainArgCabalSpec args)
+               (putStrLn "Ignoring Cabal library specification as cabal-install tests are not running")
+          return Nothing
+        -- Path to cabal-install is passed, so need to install the requested relevant version of Cabal
+        -- library.
+        Just {} ->
+          case mainArgCabalSpec args of
+            Nothing -> do
+              putStrLn "No Cabal library specified, using boot Cabal library with cabal-install tests"
+              return Nothing
+            Just BootCabalLib -> return Nothing
+            Just (InTreeCabalLib root build_dir) ->
+              Just <$> buildCabalLibsIntree root verbosity (argGhcPath (mainCommonArgs args)) build_dir
+            Just (SpecificCabalLib ver build_dir) ->
+              Just <$> buildCabalLibsSpecific ver verbosity (argGhcPath (mainCommonArgs args)) build_dir
+
     -- To run our test scripts, we need to be able to run Haskell code
     -- linked against the Cabal library under test.  The most efficient
     -- way to get this information is by querying the *host* build
@@ -140,7 +222,7 @@ main = do
                 -> IO result
         runTest runner path
             = runner Nothing [] path $
-                ["--builddir", dist_dir, path] ++ renderCommonArgs (mainCommonArgs args)
+                ["--builddir", dist_dir, path] ++ ["--extra-package-db=" ++ pkg_db | Just pkg_db <- [mpkg_db]] ++ renderCommonArgs (mainCommonArgs args)
 
     case mainArgTestPaths args of
         [path] -> do
diff --git a/cabal-testsuite/src/Test/Cabal/Monad.hs b/cabal-testsuite/src/Test/Cabal/Monad.hs
index 14e9313506432e1119c44aafd9bf992cdadbbd8b..5e8ebf1abbb22fc6ae1f0deca300287d3eb1b1ca 100644
--- a/cabal-testsuite/src/Test/Cabal/Monad.hs
+++ b/cabal-testsuite/src/Test/Cabal/Monad.hs
@@ -157,6 +157,7 @@ renderCommonArgs args =
 
 data TestArgs = TestArgs {
         testArgDistDir    :: FilePath,
+        testArgPackageDb  :: Maybe FilePath,
         testArgScriptPath :: FilePath,
         testCommonArgs    :: CommonArgs
     }
@@ -167,6 +168,10 @@ testArgParser = TestArgs
         ( help "Build directory of cabal-testsuite"
        <> long "builddir"
        <> metavar "DIR")
+    <*> optional (option str
+        ( help "Package DB which contains Cabal and Cabal-syntax"
+       <> long "extra-package-db"
+       <> metavar "DIR"))
     <*> argument str ( metavar "FILE")
     <*> commonArgParser
 
@@ -321,6 +326,7 @@ runTestM mode m =
                     testMtimeChangeDelay = Nothing,
                     testScriptEnv = senv,
                     testSetupPath = dist_dir </> "build" </> "setup" </> "setup",
+                    testPackageDbPath = testArgPackageDb args,
                     testSkipSetupTests =  argSkipSetupTests (testCommonArgs args),
                     testHaveCabalShared = runnerWithSharedLib senv,
                     testEnvironment =
@@ -615,6 +621,9 @@ data TestEnv = TestEnv
     , testScriptEnv :: ScriptEnv
     -- | Setup script path
     , testSetupPath :: FilePath
+    -- | Setup package-db path which contains Cabal and Cabal-syntax for cabal-install to
+    -- use when compiling custom setups.
+    , testPackageDbPath :: Maybe FilePath
     -- | Skip Setup tests?
     , testSkipSetupTests :: Bool
     -- | Do we have shared libraries for the Cabal-under-tests?
diff --git a/cabal-testsuite/src/Test/Cabal/Prelude.hs b/cabal-testsuite/src/Test/Cabal/Prelude.hs
index 22f109f16af67420eff22b7bf50bdd6338231ab1..4923b3e488465eedfb243d120813c0a9e67133da 100644
--- a/cabal-testsuite/src/Test/Cabal/Prelude.hs
+++ b/cabal-testsuite/src/Test/Cabal/Prelude.hs
@@ -35,7 +35,7 @@ import Distribution.Simple.Utils
     ( withFileContents, tryFindPackageDesc )
 import Distribution.Version
 import Distribution.Package
-import Distribution.Parsec (eitherParsec)
+import Distribution.Parsec (eitherParsec, simpleParsec)
 import Distribution.Types.UnqualComponentName
 import Distribution.Types.LocalBuildInfo
 import Distribution.PackageDescription
@@ -318,6 +318,7 @@ cabalGArgs global_args cmd args input = do
           = [ "--builddir", testDistDir env
             , "-j1" ]
             ++ [ "--project-file=" ++ fp | Just fp <- [testCabalProjectFile env] ]
+            ++ ["--package-db=" ++ db | Just db <- [testPackageDbPath env]]
 
           | otherwise
           = [ "--builddir", testDistDir env ] ++
@@ -399,6 +400,12 @@ withPackageDb m = do
                $ do ghcPkg "init" [db_path]
                     m
 
+-- | Don't pass `--package-db` to cabal-install, so it won't find the specific version of
+-- `Cabal` which you have configured the testsuite to run with. You probably don't want to use
+-- this unless you are testing the `--package-db` flag itself.
+noCabalPackageDb :: TestM a -> TestM a
+noCabalPackageDb m = withReaderT (\nenv -> nenv { testPackageDbPath = Nothing }) m
+
 ghcPkg :: String -> [String] -> TestM ()
 ghcPkg cmd args = void (ghcPkg' cmd args)
 
@@ -840,6 +847,44 @@ hasCabalShared = do
   env <- getTestEnv
   return (testHaveCabalShared env)
 
+
+anyCabalVersion :: WithCallStack ( String -> TestM Bool )
+anyCabalVersion = isCabalVersion any
+
+allCabalVersion :: WithCallStack ( String -> TestM Bool )
+allCabalVersion = isCabalVersion all
+
+-- Used by cabal-install tests to determine which Cabal library versions are
+-- available. Given a version range, and a predicate on version ranges,
+-- are there any installed packages Cabal library
+-- versions which satisfy these.
+isCabalVersion :: WithCallStack (((Version -> Bool) -> [Version] -> Bool) -> String -> TestM Bool)
+isCabalVersion decide range = do
+  env <- getTestEnv
+  cabal_pkgs <- ghcPkg_raw' $ ["--global", "list", "Cabal", "--simple"] ++ ["--package-db=" ++ db | Just db <- [testPackageDbPath env]]
+  let pkg_versions :: [PackageIdentifier] = mapMaybe simpleParsec (words (resultOutput cabal_pkgs))
+  vr <- case eitherParsec range of
+          Left err -> fail err
+          Right vr -> return vr
+  return $ decide (`withinRange` vr)  (map pkgVersion pkg_versions)
+
+-- | Skip a test unless any available Cabal library version matches the predicate.
+skipUnlessAnyCabalVersion :: String -> TestM ()
+skipUnlessAnyCabalVersion range = skipUnless ("needs any Cabal " ++ range) =<< anyCabalVersion range
+
+
+-- | Skip a test if any available Cabal library version matches the predicate.
+skipIfAnyCabalVersion :: String -> TestM ()
+skipIfAnyCabalVersion range = skipIf ("incompatible with Cabal " ++ range) =<< anyCabalVersion range
+
+-- | Skip a test unless all Cabal library versions match the predicate.
+skipUnlessAllCabalVersion :: String -> TestM ()
+skipUnlessAllCabalVersion range = skipUnless ("needs all Cabal " ++ range) =<< allCabalVersion range
+
+-- | Skip a test if all the Cabal library version matches a predicate.
+skipIfAllCabalVersion :: String -> TestM ()
+skipIfAllCabalVersion range = skipIf ("incompatible with Cabal " ++ range) =<< allCabalVersion range
+
 isGhcVersion :: WithCallStack (String -> TestM Bool)
 isGhcVersion range = do
     ghc_program <- requireProgramM ghcProgram
@@ -894,24 +939,6 @@ getOpenFilesLimit = liftIO $ do
         _                                     -> return Nothing
 #endif
 
-hasCabalForGhc :: TestM Bool
-hasCabalForGhc = do
-    env <- getTestEnv
-    ghc_program <- requireProgramM ghcProgram
-    (runner_ghc_program, _) <- liftIO $ requireProgram
-        (testVerbosity env)
-        ghcProgram
-        (runnerProgramDb (testScriptEnv env))
-
-    -- TODO: I guess, to be more robust what we should check for
-    -- specifically is that the Cabal library we want to use
-    -- will be picked up by the package db stack of ghc-program
-
-    -- liftIO $ putStrLn $ "ghc_program:        " ++ show ghc_program
-    -- liftIO $ putStrLn $ "runner_ghc_program: " ++ show runner_ghc_program
-
-    return (programPath ghc_program == programPath runner_ghc_program)
-
 -- | If you want to use a Custom setup with new-build, it needs to
 -- be 1.20 or later.  Ordinarily, Cabal can go off and build a
 -- sufficiently recent Cabal if necessary, but in our test suite,
@@ -972,6 +999,12 @@ ghc' args = do
     recordHeader ["ghc"]
     runProgramM ghcProgram args Nothing
 
+ghcPkg_raw' :: [String] -> TestM Result
+ghcPkg_raw' args = do
+  recordHeader ["ghc-pkg"]
+  runProgramM ghcPkgProgram args Nothing
+
+
 python3 :: [String] -> TestM ()
 python3 args = void $ python3' args
 
diff --git a/validate.sh b/validate.sh
index aa60c17ab20731b277f01af5b86226f8380785ef..9edc87eeaf34eba82c2b071a3fc8a0c688622d79 100755
--- a/validate.sh
+++ b/validate.sh
@@ -468,7 +468,7 @@ CMD="$($CABALLISTBIN cabal-install:test:integration-tests2) -j1 --hide-successes
 step_cli_suite() {
 print_header "cabal-install: cabal-testsuite"
 
-CMD="$($CABALLISTBIN cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR --with-cabal=$($CABALLISTBIN cabal-install:exe:cabal) $TESTSUITEJOBS  --with-ghc=$HC --hide-successes"
+CMD="$($CABALLISTBIN cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR --with-cabal=$($CABALLISTBIN cabal-install:exe:cabal) $TESTSUITEJOBS  --with-ghc=$HC --hide-successes --intree-cabal-lib=$PWD --test-tmp=$PWD/testdb"
 (cd cabal-testsuite && timed $CMD) || exit 1
 }