Skip to content

Commit

Permalink
Add integration tests for setup script handling
Browse files Browse the repository at this point in the history
Covers 3 of the 4 possible cases:
1. explicit custom setup deps
2. custom setup with implicit/default deps
4. non-custom setup using the internal cabal lib version

case 3 is a non-custom setup but where we're forced to use an external
cabal lib version. This case is hard to test since it only happens when
it's a newer (not older) Cabal lib version that the package requires,
e.g. a .cabal file that specifies cabal-version: >= 2.0.

Also, add a --with-ghc option to the integration test suite, which lets us
more easily test with different ghc versions.

Also, don't use parallel builds in any of the integration tests, as the
self-exec method will not work, and some tests need to install deps for
some ghc versions.
  • Loading branch information
dcoutts committed May 27, 2016
1 parent 5c93eef commit 02464ab
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 26 deletions.
12 changes: 11 additions & 1 deletion cabal-install/cabal-install.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ Extra-Source-Files:
tests/IntegrationTests/user-config/uses_CABAL_CONFIG.out
tests/IntegrationTests/user-config/uses_CABAL_CONFIG.sh
tests/IntegrationTests2.hs
tests/IntegrationTests2/build/setup-custom1/A.hs
tests/IntegrationTests2/build/setup-custom1/Setup.hs
tests/IntegrationTests2/build/setup-custom1/a.cabal
tests/IntegrationTests2/build/setup-custom2/A.hs
tests/IntegrationTests2/build/setup-custom2/Setup.hs
tests/IntegrationTests2/build/setup-custom2/a.cabal
tests/IntegrationTests2/build/setup-simple/A.hs
tests/IntegrationTests2/build/setup-simple/Setup.hs
tests/IntegrationTests2/build/setup-simple/a.cabal
tests/IntegrationTests2/exception/build/Main.hs
tests/IntegrationTests2/exception/build/a.cabal
tests/IntegrationTests2/exception/configure/a.cabal
Expand Down Expand Up @@ -547,7 +556,8 @@ test-suite integration-tests2
time,
zlib,
tasty,
tasty-hunit
tasty-hunit,
tagged

if flag(old-bytestring)
build-depends: bytestring-builder
Expand Down
144 changes: 119 additions & 25 deletions cabal-install/tests/IntegrationTests2.hs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE CPP, DeriveDataTypeable #-}
module Main where

import Distribution.Client.DistDirLayout
import Distribution.Client.ProjectConfig
import Distribution.Client.Config (defaultCabalDir)
import Distribution.Client.ProjectPlanning
import Distribution.Client.ProjectPlanning.Types
import Distribution.Client.ProjectBuilding
import qualified Distribution.Client.InstallPlan as InstallPlan
import Distribution.Client.Types (GenericReadyPackage(..), installedPackageId)

import Distribution.Package hiding (installedPackageId)
import Distribution.PackageDescription
import Distribution.InstalledPackageInfo (InstalledPackageInfo)
import Distribution.Simple.Setup (toFlag)
import Distribution.Version
import Distribution.Verbosity
import Distribution.Text
Expand All @@ -26,34 +29,47 @@ import System.Directory

import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.Options
import Data.Tagged (Tagged(..))
import Data.Proxy (Proxy(..))
import Data.Typeable (Typeable)


main :: IO ()
main = defaultMain (testGroup "Integration tests (internal)" tests)

tests :: [TestTree]
tests =
main =
defaultMainWithIngredients
(defaultIngredients ++ [includingOptions projectConfigOptionDescriptions])
(withProjectConfig $ \config ->
testGroup "Integration tests (internal)"
(tests config))

tests :: ProjectConfig -> [TestTree]
tests config =
--TODO: tests for:
-- * normal success
-- * dry-run tests with changes
[ testGroup "Exceptions during discovey and planning" $
[ testCase "no package" testExceptionInFindingPackage
, testCase "no package2" testExceptionInFindingPackage2
[ testCase "no package" (testExceptionInFindingPackage config)
, testCase "no package2" (testExceptionInFindingPackage2 config)
]
, testGroup "Exceptions during building (local inplace)" $
[ testCase "configure" testExceptionInConfigureStep
, testCase "build" testExceptionInBuildStep
[ testCase "configure" (testExceptionInConfigureStep config)
, testCase "build" (testExceptionInBuildStep config)
-- , testCase "register" testExceptionInRegisterStep
]
--TODO: need to repeat for packages for the store

, testGroup "Successful builds" $
[ testCaseSteps "Setup script styles" (testSetupScriptStyles config)
]

, testGroup "Regression tests" $
[ testCase "issue #3324" testRegressionIssue3324
[ testCase "issue #3324" (testRegressionIssue3324 config)
]
]

testExceptionInFindingPackage :: Assertion
testExceptionInFindingPackage = do
testExceptionInFindingPackage :: ProjectConfig -> Assertion
testExceptionInFindingPackage config = do
BadPackageLocations locs <- expectException "BadPackageLocations" $
void $ planProject testdir config
case locs of
Expand All @@ -62,11 +78,10 @@ testExceptionInFindingPackage = do
cleanProject testdir
where
testdir = "exception/no-pkg"
config = mempty


testExceptionInFindingPackage2 :: Assertion
testExceptionInFindingPackage2 = do
testExceptionInFindingPackage2 :: ProjectConfig -> Assertion
testExceptionInFindingPackage2 config = do
BadPackageLocations locs <- expectException "BadPackageLocations" $
void $ planProject testdir config
case locs of
Expand All @@ -75,11 +90,10 @@ testExceptionInFindingPackage2 = do
cleanProject testdir
where
testdir = "exception/no-pkg2"
config = mempty


testExceptionInConfigureStep :: Assertion
testExceptionInConfigureStep = do
testExceptionInConfigureStep :: ProjectConfig -> Assertion
testExceptionInConfigureStep config = do
plan <- planProject testdir config
plan' <- executePlan plan
(_pkga1, failure) <- expectPackageFailed plan' pkgidA1
Expand All @@ -89,25 +103,68 @@ testExceptionInConfigureStep = do
cleanProject testdir
where
testdir = "exception/configure"
config = mempty
pkgidA1 = PackageIdentifier (PackageName "a") (Version [1] [])


testExceptionInBuildStep :: Assertion
testExceptionInBuildStep = do
testExceptionInBuildStep :: ProjectConfig -> Assertion
testExceptionInBuildStep config = do
plan <- planProject testdir config
plan' <- executePlan plan
(_pkga1, failure) <- expectPackageFailed plan' pkgidA1
expectBuildFailed failure
where
testdir = "exception/build"
config = mempty
pkgidA1 = PackageIdentifier (PackageName "a") (Version [1] [])

testSetupScriptStyles :: ProjectConfig -> (String -> IO ()) -> Assertion
testSetupScriptStyles config reportSubCase = do

reportSubCase (show SetupCustomExplicitDeps)
plan1 <- executePlan =<< planProject testdir1 config
(pkg1, _, _) <- expectPackageInstalled plan1 pkgidA
pkgSetupScriptStyle pkg1 @?= SetupCustomExplicitDeps
hasDefaultSetupDeps pkg1 @?= Just False
marker1 <- readFile (basedir </> testdir1 </> "marker")
marker1 @?= "ok"
removeFile (basedir </> testdir1 </> "marker")

reportSubCase (show SetupCustomImplicitDeps)
plan2 <- executePlan =<< planProject testdir2 config
(pkg2, _, _) <- expectPackageInstalled plan2 pkgidA
pkgSetupScriptStyle pkg2 @?= SetupCustomImplicitDeps
hasDefaultSetupDeps pkg2 @?= Just True
marker2 <- readFile (basedir </> testdir2 </> "marker")
marker2 @?= "ok"
removeFile (basedir </> testdir2 </> "marker")

reportSubCase (show SetupNonCustomInternalLib)
plan3 <- executePlan =<< planProject testdir3 config
(pkg3, _, _) <- expectPackageInstalled plan3 pkgidA
pkgSetupScriptStyle pkg3 @?= SetupNonCustomInternalLib
{-
--TODO: the SetupNonCustomExternalLib case is hard to test since it
-- requires a version of Cabal that's later than the one we're testing
-- e.g. needs a .cabal file that specifies cabal-version: >= 2.0
-- and a corresponding Cabal package that we can use to try and build a
-- default Setup.hs.
reportSubCase (show SetupNonCustomExternalLib)
plan4 <- executePlan =<< planProject testdir4 config
(pkg4, _, _) <- expectPackageInstalled plan4 pkgidA
pkgSetupScriptStyle pkg4 @?= SetupNonCustomExternalLib
-}
where
testdir1 = "build/setup-custom1"
testdir2 = "build/setup-custom2"
testdir3 = "build/setup-simple"
pkgidA = PackageIdentifier (PackageName "a") (Version [0,1] [])
-- The solver fills in default setup deps explicitly, but marks them as such
hasDefaultSetupDeps = fmap defaultSetupDepends
. setupBuildInfo . pkgDescription

-- | See <https://github.com/haskell/cabal/issues/3324>
--
testRegressionIssue3324 :: Assertion
testRegressionIssue3324 = do
testRegressionIssue3324 :: ProjectConfig -> Assertion
testRegressionIssue3324 config = do
-- expected failure first time due to missing dep
plan1 <- executePlan =<< planProject testdir config
(_pkgq, failure) <- expectPackageFailed plan1 pkgidQ
Expand All @@ -123,7 +180,6 @@ testRegressionIssue3324 = do
return ()
where
testdir = "regression/3324"
config = mempty
pkgidP = PackageIdentifier (PackageName "p") (Version [0,1] [])
pkgidQ = PackageIdentifier (PackageName "q") (Version [0,1] [])

Expand Down Expand Up @@ -209,6 +265,44 @@ cleanProject testdir = do
verbosity :: Verbosity
verbosity = minBound --normal --verbose --maxBound --minBound



-------------------------------------------
-- Tasty integration to adjust the config
--

withProjectConfig :: (ProjectConfig -> TestTree) -> TestTree
withProjectConfig testtree =
askOption $ \ghcPath ->
testtree (mkProjectConfig ghcPath)

mkProjectConfig :: GhcPath -> ProjectConfig
mkProjectConfig (GhcPath ghcPath) =
mempty {
projectConfigShared = mempty {
projectConfigHcPath = maybeToFlag ghcPath
},
projectConfigBuildOnly = mempty {
projectConfigNumJobs = toFlag (Just 1)
}
}
where
maybeToFlag = maybe mempty toFlag


data GhcPath = GhcPath (Maybe FilePath)
deriving Typeable

instance IsOption GhcPath where
defaultValue = GhcPath Nothing
optionName = Tagged "with-ghc"
optionHelp = Tagged "The ghc compiler to use"
parseValue = Just . GhcPath . Just

projectConfigOptionDescriptions :: [OptionDescription]
projectConfigOptionDescriptions = [Option (Proxy :: Proxy GhcPath)]


---------------------------------------
-- HUint style utils for this context
--
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A where

a :: Int
a = 42
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain >> writeFile "marker" "ok"
13 changes: 13 additions & 0 deletions cabal-install/tests/IntegrationTests2/build/setup-custom1/a.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: a
version: 0.1
build-type: Custom
cabal-version: >= 1.10

-- explicit setup deps:
custom-setup
setup-depends: base, Cabal >= 1.18

library
exposed-modules: A
build-depends: base
default-language: Haskell2010
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A where

a :: Int
a = 42
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain >> writeFile "marker" "ok"
11 changes: 11 additions & 0 deletions cabal-install/tests/IntegrationTests2/build/setup-custom2/a.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: a
version: 0.1
build-type: Custom
cabal-version: >= 1.10

-- no explicit setup deps

library
exposed-modules: A
build-depends: base
default-language: Haskell2010
4 changes: 4 additions & 0 deletions cabal-install/tests/IntegrationTests2/build/setup-simple/A.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A where

a :: Int
a = 42
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: a
version: 0.1
build-type: Simple
cabal-version: >= 1.10

library
exposed-modules: A
build-depends: base
default-language: Haskell2010

0 comments on commit 02464ab

Please sign in to comment.