Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Only buildable tests #7829

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
8 changes: 8 additions & 0 deletions Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import Distribution.Simple.Setup (HaddockTarget (..), TestShow
import Distribution.SPDX
import Distribution.System
import Distribution.Types.Dependency
import Distribution.Types.EnableComponentType
import Distribution.Types.Flag (FlagAssignment, FlagName, mkFlagAssignment, mkFlagName, unFlagAssignment)
import Distribution.Types.IncludeRenaming
import Distribution.Types.LibraryName
Expand Down Expand Up @@ -493,6 +494,13 @@ instance Arbitrary PackageDB where
instance Arbitrary DumpBuildInfo where
arbitrary = arbitraryBoundedEnum

-------------------------------------------------------------------------------
-- EnableComponentType
-------------------------------------------------------------------------------

instance Arbitrary EnableComponentType where
arbitrary = arbitraryBoundedEnum

-------------------------------------------------------------------------------
-- Helpers
-------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions Cabal/Cabal.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ library
Distribution.Types.VersionInterval.Legacy
Distribution.Types.GivenComponent
Distribution.Types.PackageVersionConstraint
Distribution.Types.EnableComponentType
Distribution.Utils.Generic
Distribution.Utils.Json
Distribution.Utils.NubList
Expand Down
10 changes: 7 additions & 3 deletions Cabal/src/Distribution/Simple/Configure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import Distribution.Types.PackageVersionConstraint
import Distribution.Types.LocalBuildInfo
import Distribution.Types.ComponentRequestedSpec
import Distribution.Types.GivenComponent
import Distribution.Types.EnableComponentType
import Distribution.Simple.Utils
import Distribution.System
import Distribution.Version
Expand Down Expand Up @@ -401,12 +402,15 @@ configure (pkg_descr0, pbi) cfg = do
-- nomenclature; it's just a request; a
-- @buildable: False@ might make it
-- not possible to enable.
{ testsRequested = fromFlag (configTests cfg)
{ testsRequested =
fromFlag (configTests cfg) == EnableAll
, benchmarksRequested =
fromFlag (configBenchmarks cfg) }
fromFlag (configBenchmarks cfg) == EnableAll
}
-- Some sanity checks related to enabling components.
when (isJust mb_cname
&& (fromFlag (configTests cfg) || fromFlag (configBenchmarks cfg))) $
&& ( fromFlag (configTests cfg) == EnableAll
|| fromFlag (configBenchmarks cfg) == EnableAll)) $
die' verbosity $
"--enable-tests/--enable-benchmarks are incompatible with" ++
" explicitly specifying a component to configure."
Expand Down
37 changes: 27 additions & 10 deletions Cabal/src/Distribution/Simple/Setup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ import Distribution.Verbosity
import Distribution.Utils.NubList
import Distribution.Types.ComponentId
import Distribution.Types.DumpBuildInfo
import Distribution.Types.EnableComponentType
import Distribution.Types.GivenComponent
import Distribution.Types.Module
import Distribution.Types.PackageVersionConstraint
Expand Down Expand Up @@ -264,8 +265,8 @@ data ConfigFlags = ConfigFlags {
-- package does not use Backpack, or we just want to typecheck
-- the indefinite package.
configConfigurationsFlags :: FlagAssignment,
configTests :: Flag Bool, -- ^Enable test suite compilation
configBenchmarks :: Flag Bool, -- ^Enable benchmark compilation
configTests :: Flag EnableComponentType, -- ^Enable test suite compilation
configBenchmarks :: Flag EnableComponentType, -- ^Enable benchmark compilation
configCoverage :: Flag Bool, -- ^Enable program coverage
configLibCoverage :: Flag Bool, -- ^Enable program coverage (deprecated)
configExactConfiguration :: Flag Bool,
Expand Down Expand Up @@ -392,8 +393,8 @@ defaultConfigFlags progDb = emptyConfigFlags {
configSplitObjs = Flag False, -- takes longer, so turn off by default
configStripExes = NoFlag,
configStripLibs = NoFlag,
configTests = Flag False,
configBenchmarks = Flag False,
configTests = Flag EnableWhenPossible,
configBenchmarks = Flag EnableWhenPossible,
configCoverage = Flag False,
configLibCoverage = NoFlag,
configExactConfiguration = Flag False,
Expand Down Expand Up @@ -698,10 +699,18 @@ configureOptions showOrParseArgs =
(parsecToReadE ("Cannot parse module substitution: " ++) (fmap (:[]) parsecModSubstEntry))
(map (Disp.renderStyle defaultStyle . dispModSubstEntry)))

,option "" ["tests"]
"dependency checking and compilation for test suites listed in the package description file."
,multiOption "tests"
configTests (\v flags -> flags { configTests = v })
(boolOpt [] [])
[noArg (Flag EnableWhenPossible) []
["enable-tests-when-possible", "enable-test-if-possible"]
"Build the tests if a build plan can be found, don't build them otherwise. The decision is made independently for each package, not for each test suite."
,noArg (Flag EnableAll) []
["enable-tests", "enable-test"]
"Build all the test suites listed in the package description file."
,noArg (Flag DisableAll) []
["disable-tests", "disable-test"]
"Do not build any test suites."
]

,option "" ["coverage"]
"build package with Haskell Program Coverage. (GHC only)"
Expand All @@ -719,10 +728,18 @@ configureOptions showOrParseArgs =
(\v flags -> flags { configExactConfiguration = v })
trueArg

,option "" ["benchmarks"]
"dependency checking and compilation for benchmarks listed in the package description file."
,multiOption "benchmarks"
configBenchmarks (\v flags -> flags { configBenchmarks = v })
(boolOpt [] [])
[noArg (Flag EnableWhenPossible) []
["enable-benchmarks-when-possible", "enable-benchmark-if-possible"]
"Build the benchmarks if a build plan can be found, don't build them otherwise. The decision is made independently for each package, not for each benchmark."
,noArg (Flag EnableAll) []
["enable-benchmarks", "enable-benchmark"]
"Build all the benchmarks listed in the package description file."
,noArg (Flag DisableAll) []
["disable-benchmarks", "disable-benchmark"]
"Do not build any benchmarks."
]

,option "" ["relocatable"]
"building a package that is relocatable. (GHC only)"
Expand Down
50 changes: 50 additions & 0 deletions Cabal/src/Distribution/Types/EnableComponentType.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Distribution.Types.EnableComponentType (
EnableComponentType(..),

defaultEnableComponentType,
enableComponentTypeToRequest,
) where

import Prelude ()
import Distribution.Compat.Prelude

-- | Which subset of a given component type to enable. Specified by option
-- triples like @--enable-tests@, @--disable-tests@, and
-- @--enable-tests-when-possible@.
--
-- @since 3.7.0.0
data EnableComponentType
= EnableAll
| DisableAll
| EnableWhenPossible
deriving (Generic, Read, Show, Eq, Typeable, Bounded, Enum)

instance Binary EnableComponentType
instance Structured EnableComponentType

-- | 'EnableComponentType' is only used for tests and benchmarks, for which the
-- default behaviour of @cabal configure@ is to try to include them in the
-- build plan if possible, and to silently drop them otherwise.
--
-- It's not a big deal to drop them because the default behaviour of @cabal
-- build@ is to build the libraries and executables, but not the tests nor the
-- benchmarks. But it's better to include them in the build plan if we can, so
-- that running @cabal test@ after @cabal build@ doesn't unnecessarily rebuild
-- because of a changed build plan.
--
-- @since 3.7.0.0
defaultEnableComponentType :: EnableComponentType
defaultEnableComponentType = EnableWhenPossible

-- | With the 'EnableAll' and 'DisableAll' settings, the user makes an explicit
-- request, either to definitely enable or to definitely disable a certain type
-- of component. However, with 'EnableWhenPossible', the user is not making any
-- request.
--
-- @since 3.7.0.0
enableComponentTypeToRequest :: EnableComponentType -> Maybe Bool
enableComponentTypeToRequest EnableAll = Just True
enableComponentTypeToRequest DisableAll = Just False
enableComponentTypeToRequest EnableWhenPossible = Nothing
14 changes: 9 additions & 5 deletions cabal-install/main/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ import Distribution.Simple.Utils
, findPackageDesc, tryFindPackageDesc )
import Distribution.Text
( display )
import Distribution.Types.EnableComponentType
( EnableComponentType(..) )
import Distribution.Verbosity as Verbosity
( normal )
import Distribution.Version
Expand Down Expand Up @@ -526,7 +528,7 @@ installAction
-- '--run-tests' implies '--enable-tests'.
maybeForceTests installFlags' configFlags' =
if fromFlagOrDefault False (installRunTests installFlags')
then configFlags' { configTests = toFlag True }
then configFlags' { configTests = toFlag EnableAll }
else configFlags'

testAction :: (BuildFlags, TestFlags) -> [String] -> GlobalFlags
Expand All @@ -538,11 +540,12 @@ testAction (buildFlags, testFlags) extraArgs globalFlags = do
let buildFlags' = buildFlags
{ buildVerbosity = testVerbosity testFlags }
checkFlags = Check $ \_ flags@(configFlags, configExFlags) ->
if fromFlagOrDefault False (configTests configFlags)
if fromFlagOrDefault EnableWhenPossible (configTests configFlags)
== EnableAll
then pure (mempty, flags)
else do
info verbosity "reconfiguring to enable tests"
let flags' = ( configFlags { configTests = toFlag True }
let flags' = ( configFlags { configTests = toFlag EnableAll }
, configExFlags
)
pure (Any True, flags')
Expand Down Expand Up @@ -612,11 +615,12 @@ benchmarkAction
{ buildVerbosity = benchmarkVerbosity benchmarkFlags }

let checkFlags = Check $ \_ flags@(configFlags, configExFlags) ->
if fromFlagOrDefault False (configBenchmarks configFlags)
if fromFlagOrDefault EnableWhenPossible (configBenchmarks configFlags)
== EnableAll
then pure (mempty, flags)
else do
info verbosity "reconfiguring to enable benchmarks"
let flags' = ( configFlags { configBenchmarks = toFlag True }
let flags' = ( configFlags { configBenchmarks = toFlag EnableAll }
, configExFlags
)
pure (Any True, flags')
Expand Down
10 changes: 6 additions & 4 deletions cabal-install/src/Distribution/Client/CmdInstall.hs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ import Distribution.Simple.GHC
, renderGhcEnvironmentFile, readGhcEnvironmentFile, ParseErrorExc )
import Distribution.System
( Platform , buildOS, OS (Windows) )
import Distribution.Types.EnableComponentType
( EnableComponentType(..) )
import Distribution.Types.UnitId
( UnitId )
import Distribution.Types.UnqualComponentName
Expand Down Expand Up @@ -408,10 +410,10 @@ verifyPreconditionsOrDie verbosity configFlags = do
-- We never try to build tests/benchmarks for remote packages.
-- So we set them as disabled by default and error if they are explicitly
-- enabled.
when (configTests configFlags == Flag True) $
when (configTests configFlags == Flag EnableAll) $
die' verbosity $ "--enable-tests was specified, but tests can't "
++ "be enabled in a remote package"
when (configBenchmarks configFlags == Flag True) $
when (configBenchmarks configFlags == Flag EnableAll) $
die' verbosity $ "--enable-benchmarks was specified, but benchmarks can't "
++ "be enabled in a remote package"

Expand Down Expand Up @@ -741,8 +743,8 @@ environmentFileToSpecifiers ipi = foldMap $ \case
-- | Disables tests and benchmarks if they weren't explicitly enabled.
disableTestsBenchsByDefault :: ConfigFlags -> ConfigFlags
disableTestsBenchsByDefault configFlags =
configFlags { configTests = Flag False <> configTests configFlags
, configBenchmarks = Flag False <> configBenchmarks configFlags }
configFlags { configTests = Flag DisableAll <> configTests configFlags
, configBenchmarks = Flag DisableAll <> configBenchmarks configFlags }

-- | Symlink/copy every exe from a package from the store to a given location
installUnitExes
Expand Down
30 changes: 28 additions & 2 deletions cabal-install/src/Distribution/Client/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ import Distribution.Verbosity
import qualified Distribution.Compat.CharParsing as P
import Distribution.Client.ProjectFlags (ProjectFlags (..))
import Distribution.Solver.Types.ConstraintSource
import Distribution.Types.EnableComponentType

import qualified Text.PrettyPrint as Disp
( render, text, empty )
Expand All @@ -143,7 +144,7 @@ import qualified Data.Map as M
import qualified Data.ByteString as BS

--
-- * Configuration saved in the config file
-- * Configuration saved in the @~/.cabal/config@ file
--

data SavedConfig = SavedConfig
Expand Down Expand Up @@ -883,8 +884,14 @@ commentSavedConfig = do
removeRootKeys :: RemoteRepo -> RemoteRepo
removeRootKeys r = r { remoteRepoRootKeys = [] }

-- | All config file fields.
-- | The parser and pretty-printer for the 'SavedConfig' fields are mostly
-- derived from the command-line options for the various commands (@cabal
-- configure@, @cabal install@, etc.). When the format in the configuration
-- file differs from the format in the command-line option, we define a
-- separate 'FieldDescr' here.
--
-- Fields which are valid in both a 'ProjectConfig' and a 'SavedConfig' also
-- need a separate 'FieldDescr' in 'legacyProjectConfigFieldDescrs'.
configFieldDescriptions :: ConstraintSource -> [FieldDescr SavedConfig]
configFieldDescriptions src =

Expand Down Expand Up @@ -957,6 +964,12 @@ configFieldDescriptions src =
caseWarning = PWarning $
"The '" ++ name
++ "' field is case sensitive, use 'True' or 'False'.")
,liftField configTests (\v flags -> flags { configTests = v }) $
let name = "tests" in
FieldDescr name prettyPrintEnableStanza (parseEnableStanza name)
,liftField configBenchmarks (\v flags -> flags { configBenchmarks = v }) $
let name = "benchmarks" in
FieldDescr name prettyPrintEnableStanza (parseEnableStanza name)
]

++ toSavedConfig liftConfigExFlag
Expand Down Expand Up @@ -1028,6 +1041,19 @@ configFieldDescriptions src =
toRelaxDeps True = RelaxDepsAll
toRelaxDeps False = mempty

prettyPrintEnableStanza NoFlag = Disp.text "EnableWhenPossible"
prettyPrintEnableStanza (Flag EnableWhenPossible) = Disp.text "EnableWhenPossible"
prettyPrintEnableStanza (Flag DisableAll) = Disp.text "DisableAll"
prettyPrintEnableStanza (Flag EnableAll) = Disp.text "EnableAll"

parseEnableStanza name line str _ = case () of
_ | str == "EnableWhenPossible" -> ParseOk [] (Flag EnableWhenPossible)
| str == "DisableAll" -> ParseOk [] (Flag DisableAll)
| str == "False" -> ParseOk [] (Flag DisableAll)
| str == "EnableAll" -> ParseOk [] (Flag EnableAll)
| str == "True" -> ParseOk [] (Flag EnableAll)
| otherwise -> ParseFailed (NoParse name line)


-- TODO: next step, make the deprecated fields elicit a warning.
--
Expand Down
16 changes: 11 additions & 5 deletions cabal-install/src/Distribution/Client/Configure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import Distribution.Simple.PackageIndex as PackageIndex
( InstalledPackageIndex, lookupPackageName )
import Distribution.Package
( Package(..), packageName, PackageId )
import Distribution.Types.EnableComponentType
import Distribution.Types.GivenComponent
( GivenComponent(..) )
import Distribution.Types.PackageVersionConstraint
Expand Down Expand Up @@ -312,10 +313,13 @@ planLocalPackage verbosity comp platform configFlags configExFlags
}

testsEnabled :: Bool
testsEnabled = fromFlagOrDefault False $ configTests configFlags
testsEnabled = fromFlagOrDefault EnableWhenPossible
(configTests configFlags)
== EnableAll
benchmarksEnabled :: Bool
benchmarksEnabled =
fromFlagOrDefault False $ configBenchmarks configFlags
benchmarksEnabled = fromFlagOrDefault EnableWhenPossible
(configBenchmarks configFlags)
== EnableAll

resolverParams :: DepResolverParams
resolverParams =
Expand Down Expand Up @@ -419,9 +423,11 @@ configurePackage verbosity platform comp scriptOptions configFlags
-- NB: if the user explicitly specified
-- --enable-tests/--enable-benchmarks, always respect it.
-- (But if they didn't, let solver decide.)
configBenchmarks = toFlag (BenchStanzas `optStanzaSetMember` stanzas)
configBenchmarks = toFlag (if BenchStanzas `optStanzaSetMember` stanzas
then EnableAll else DisableAll)
`mappend` configBenchmarks configFlags,
configTests = toFlag (TestStanzas `optStanzaSetMember` stanzas)
configTests = toFlag (if TestStanzas `optStanzaSetMember` stanzas
then EnableAll else DisableAll)
`mappend` configTests configFlags
}

Expand Down
Loading