Skip to content

Commit 7b94e0b

Browse files
committed
SetupHooks: add tests
This adds tests for error messages related to SetupHooks: - error when returning an invalid component diff in a per-component pre-configure hook - error when declaring pre-build rules whose dependency graph contains cycles - error when we cannot find a dependency of a pre-build rule - warning when there are pre-build rules that are declared but never demanded It also adds some correctness tests for SetupHooks, e.g. that pre-build rules are run in dependency order (see the `SetupHooksRuleOrdering` test).
1 parent 4382956 commit 7b94e0b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+505
-18
lines changed

Cabal-hooks/src/Distribution/Simple/SetupHooks.hs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -428,10 +428,10 @@ rather than directly using the v'Rules', v'Rule' and v'Action' constructors,
428428
which insulates us from internal changes to the t'Rules', t'Rule' and t'Action'
429429
datatypes, respectively.
430430
431-
We use 'declareRuleDependencies' to declare that the collection of rules as a
432-
whole depends on. In this case, we declare that they depend on the contents of
433-
the "searchDir" directory. This means that the rules will be computed anew
434-
whenever the contents of this directory change.
431+
We use 'addRuleMonitorss' to declare a monitored directory that the collection
432+
of rules as a whole depends on. In this case, we declare that they depend on the
433+
contents of the "searchDir" directory. This means that the rules will be
434+
computed anew whenever the contents of this directory change.
435435
436436
Additional convenience functions are also provided, such as the 'generateModules'
437437
function which can be used to generate a collection of modules ex nihilo without
@@ -633,16 +633,14 @@ register_helper mkId mkDupIdErr i newX = do
633633
[] -> ""
634634
(_, SrcLoc { srcLocPackage = pkg }) : _ -> toShortText pkg
635635

636-
-- | Declare a dependency for the collection of all rules.
636+
-- | Declare additional monitored objects for the collection of all rules.
637637
--
638638
-- When these monitored objects change, the rules are re-computed.
639639
addRuleMonitors :: Monad m => [ MonitorFileOrDir ] -> RulesT m ()
640640
addRuleMonitors = RulesT . lift . lift . Writer.tell
641641
{-# INLINEABLE addRuleMonitors #-}
642642

643643
-- | Find a file in the given search directories.
644-
--
645-
--
646644
findFileInDirs :: FilePath -> [FilePath] -> IO (Maybe Location)
647645
findFileInDirs file dirs =
648646
findFirstFile

Cabal/src/Distribution/Simple/SetupHooks/Internal.hs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ data PreConfPackageInputs = PreConfPackageInputs
203203
-- of this datatype.
204204
data PreConfPackageOutputs = PreConfPackageOutputs
205205
{ buildOptions :: BuildOptions
206-
, extraConfiguredPrograms :: ConfiguredProgs
206+
, extraConfiguredProgs :: ConfiguredProgs
207207
}
208208
deriving (Generic, Show)
209209

@@ -217,7 +217,7 @@ noPreConfPackageOutputs :: PreConfPackageInputs -> PreConfPackageOutputs
217217
noPreConfPackageOutputs (PreConfPackageInputs{localBuildConfig = lbc}) =
218218
PreConfPackageOutputs
219219
{ buildOptions = LBC.withBuildOptions lbc
220-
, extraConfiguredPrograms = Map.empty
220+
, extraConfiguredProgs = Map.empty
221221
}
222222

223223
-- | Package-wide post-configure step.
@@ -349,12 +349,12 @@ instance Semigroup PreConfPkgSemigroup where
349349
do
350350
PreConfPackageOutputs
351351
{ buildOptions = opts1
352-
, extraConfiguredPrograms = progs1
352+
, extraConfiguredProgs = progs1
353353
} <-
354354
f1 inputs
355355
PreConfPackageOutputs
356356
{ buildOptions = opts2
357-
, extraConfiguredPrograms = progs2
357+
, extraConfiguredProgs = progs2
358358
} <-
359359
f2 $
360360
PreConfPackageInputs
@@ -372,7 +372,7 @@ instance Semigroup PreConfPkgSemigroup where
372372
return $
373373
PreConfPackageOutputs
374374
{ buildOptions = opts2
375-
, extraConfiguredPrograms = progs1 <> progs2
375+
, extraConfiguredProgs = progs1 <> progs2
376376
}
377377

378378
-- | A newtype to hang off the @Semigroup PreConfComponentHook@ instance.

Cabal/src/Distribution/Simple/SetupHooks/Rule.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ instance Binary Rule
249249
instance Structured Rule
250250

251251
-- | A (fully resolved) location of a dependency or result of a rule,
252-
-- consisting of an absolute path and of a file path relative to that base path.
252+
-- consisting of a base directory and of a file path relative to that base
253+
-- directory path.
253254
--
254255
-- In practice, this will be something like @( dir, toFilePath modName )@,
255256
-- where:
@@ -324,7 +325,7 @@ newtype Action
324325
-- \^ Locations of the __dependencies__ of this action,
325326
-- as declared by the rule that this action is executing.
326327
-> NE.NonEmpty Location
327-
-- \^ Locations in which the __results_ of this action
328+
-- \^ Locations in which the __results__ of this action
328329
-- should be put.
329330
-> IO ()
330331
}
@@ -341,8 +342,9 @@ simpleAction f = Action{action = f}
341342
-- constructor.
342343
--
343344
-- Actions are registered using 'registerAction', and rules are registered
344-
-- using 'registerRule'. Additional rule dependencies (whose changes should
345-
-- trigger rule recompilation) are declared using 'declareRuleDependencies'.
345+
-- using 'registerRule'. One can declare additional monitored files or
346+
-- directories using 'addRuleMonitors'; a change in these will trigger the
347+
-- recomputation of all rules.
346348
--
347349
-- The @env@ type parameter represents an extra argument, which usually
348350
-- consists of information known to Cabal such as 'LocalBuildInfo' and
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Main where
2+
3+
import Distribution.Simple ( defaultMainWithSetupHooks )
4+
import SetupHooks ( setupHooks )
5+
6+
main :: IO ()
7+
main = defaultMainWithSetupHooks setupHooks
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module SetupHooks where
2+
3+
import Distribution.Simple.SetupHooks
4+
5+
import Control.Monad ( void )
6+
7+
setupHooks :: SetupHooks
8+
setupHooks =
9+
noSetupHooks
10+
{ configureHooks =
11+
noConfigureHooks
12+
{ preConfComponentHook = Just pccHook }
13+
}
14+
15+
pccHook :: PreConfComponentHook
16+
pccHook _ = return $
17+
PreConfComponentOutputs $ ComponentDiff $ CExe emptyExecutable
18+
-- Bad: component is a library, but we returned an executable!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: .
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
cabal-version: 2.2
2+
name: setup-hooks-bad-diff1-test
3+
version: 0.1.0.0
4+
synopsis: Test 1 for a bad component diff
5+
license: BSD-3-Clause
6+
author: NA
7+
maintainer: NA
8+
category: Testing
9+
build-type: Hooks
10+
11+
custom-setup
12+
setup-depends: Cabal-hooks, base
13+
14+
library
15+
build-depends: base
16+
default-language: Haskell2010
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Setup configure
2+
Configuring setup-hooks-bad-diff1-test-0.1.0.0...
3+
Error: [Cabal-9491]
4+
Hooks: mismatched component types in per-component configure hook.
5+
Trying to apply an executable diff to a library.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Test.Cabal.Prelude
2+
main = setupTest $ do
3+
fails $ setup "configure" []
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Main where
2+
3+
import Distribution.Simple ( defaultMainWithSetupHooks )
4+
import SetupHooks ( setupHooks )
5+
6+
main :: IO ()
7+
main = defaultMainWithSetupHooks setupHooks
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
3+
module SetupHooks where
4+
5+
import Distribution.Simple.SetupHooks
6+
7+
import Control.Monad ( void )
8+
9+
setupHooks :: SetupHooks
10+
setupHooks =
11+
noSetupHooks
12+
{ configureHooks =
13+
noConfigureHooks
14+
{ preConfComponentHook = Just pccHook }
15+
}
16+
17+
pccHook :: PreConfComponentHook
18+
pccHook _ = return $
19+
-- Make invalid changes to a library
20+
PreConfComponentOutputs $ ComponentDiff $ CLib $
21+
emptyLibrary
22+
{ libName = LSubLibName "hocus-pocus"
23+
, libExposed = False
24+
, libBuildInfo =
25+
emptyBuildInfo
26+
{ buildable = False }
27+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: .
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
cabal-version: 2.2
2+
name: setup-hooks-bad-diff2-test
3+
version: 0.1.0.0
4+
synopsis: Test 2 for a bad component diff
5+
license: BSD-3-Clause
6+
author: NA
7+
maintainer: NA
8+
category: Testing
9+
build-type: Hooks
10+
11+
custom-setup
12+
setup-depends: Cabal-hooks, base
13+
14+
library
15+
build-depends: base
16+
default-language: Haskell2010
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Setup configure
2+
Configuring setup-hooks-bad-diff2-test-0.1.0.0...
3+
Error: [Cabal-7634]
4+
Hooks: illegal component diff in per-component pre-configure hook for main library:
5+
- cannot change the name of a component.
6+
- cannot change component field 'libExposed'.
7+
- cannot change BuildInfo field 'buildable'.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Test.Cabal.Prelude
2+
main = setupTest $ do
3+
fails $ setup "configure" []
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Main where
2+
3+
import Distribution.Simple ( defaultMainWithSetupHooks )
4+
import SetupHooks ( setupHooks )
5+
6+
main :: IO ()
7+
main = defaultMainWithSetupHooks setupHooks
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{-# LANGUAGE DuplicateRecordFields #-}
2+
{-# LANGUAGE OverloadedStrings #-}
3+
{-# LANGUAGE RecursiveDo #-}
4+
5+
module SetupHooks where
6+
7+
import Distribution.Simple.SetupHooks
8+
9+
import qualified Data.List.NonEmpty as NE ( NonEmpty(..) )
10+
11+
setupHooks :: SetupHooks
12+
setupHooks =
13+
noSetupHooks
14+
{ buildHooks =
15+
noBuildHooks
16+
{ preBuildComponentRules = Just cyclicPreBuildRules
17+
}
18+
}
19+
20+
cyclicPreBuildRules :: Rules PreBuildComponentInputs
21+
cyclicPreBuildRules = rules $ \ (PreBuildComponentInputs { localBuildInfo = lbi, targetInfo = tgt }) -> do
22+
let clbi = targetCLBI tgt
23+
autogenDir = autogenComponentModulesDir lbi clbi
24+
actId <- registerAction "a" $ simpleAction $ \ _ _ -> error "This should not run"
25+
return $ mdo
26+
r1 <- registerRule "r1" $
27+
simpleRule actId
28+
[ RuleDependency $ RuleOutput r2 0 ]
29+
( ( autogenDir, "G2.hs" ) NE.:| [] )
30+
r2 <- registerRule "r2" $
31+
simpleRule actId
32+
[ RuleDependency $ RuleOutput r1 0 ]
33+
( ( autogenDir, "G1.hs" ) NE.:| [] )
34+
return ()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: .
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cabal-version: 2.2
2+
name: setup-hooks-cyclic-rules-test
3+
version: 0.1.0.0
4+
synopsis: Test for cyclic rules
5+
license: BSD-3-Clause
6+
author: NA
7+
maintainer: NA
8+
category: Testing
9+
build-type: Hooks
10+
11+
custom-setup
12+
setup-depends: Cabal-hooks, base
13+
14+
library
15+
exposed-modules: G1, G2
16+
autogen-modules: G1, G2
17+
build-depends: base
18+
default-language: Haskell2010
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Setup configure
2+
Configuring setup-hooks-cyclic-rules-test-0.1.0.0...
3+
# Setup build
4+
Error: [Cabal-9077]
5+
Hooks: cycle in dependency structure of rules:
6+
Rule: [(RuleId {ruleUnitId = "main", ruleId = "r2"})[0]] --> [setup.dist/work/dist/build/autogen/G2.hs]
7+
|
8+
`- Rule: [(RuleId {ruleUnitId = "main", ruleId = "r1"})[0]] --> [setup.dist/work/dist/build/autogen/G1.hs]
9+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import Test.Cabal.Prelude
2+
main = setupTest $ do
3+
setup "configure" []
4+
fails $ setup "build" []
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Main where
2+
3+
import Distribution.Simple ( defaultMainWithSetupHooks )
4+
import SetupHooks ( setupHooks )
5+
6+
main :: IO ()
7+
main = defaultMainWithSetupHooks setupHooks
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{-# LANGUAGE DuplicateRecordFields #-}
2+
{-# LANGUAGE OverloadedStrings #-}
3+
4+
module SetupHooks where
5+
6+
import Distribution.Simple.SetupHooks
7+
8+
import qualified Data.List.NonEmpty as NE ( NonEmpty(..) )
9+
10+
setupHooks :: SetupHooks
11+
setupHooks =
12+
noSetupHooks
13+
{ buildHooks =
14+
noBuildHooks
15+
{ preBuildComponentRules = Just missingDepRules
16+
}
17+
}
18+
19+
missingDepRules :: Rules PreBuildComponentInputs
20+
missingDepRules = rules $ \ (PreBuildComponentInputs { localBuildInfo = lbi, targetInfo = tgt }) -> do
21+
let clbi = targetCLBI tgt
22+
autogenDir = autogenComponentModulesDir lbi clbi
23+
actId <- registerAction "a" $ simpleAction $ \ _ _ -> error "This should not run"
24+
return $
25+
registerRule_ "r" $
26+
simpleRule actId
27+
[ FileDependency ( ".", "Missing.hs" ) ]
28+
( ( autogenDir, "G.hs" ) NE.:| [] )
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: .
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cabal-version: 2.2
2+
name: setup-hooks-missing-rule-dep-test
3+
version: 0.1.0.0
4+
synopsis: Test for missing dependency in rules
5+
license: BSD-3-Clause
6+
author: NA
7+
maintainer: NA
8+
category: Testing
9+
build-type: Hooks
10+
11+
custom-setup
12+
setup-depends: Cabal-hooks, base
13+
14+
library
15+
exposed-modules: G
16+
autogen-modules: G
17+
build-depends: base
18+
default-language: Haskell2010
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Setup configure
2+
Configuring setup-hooks-missing-rule-dep-test-0.1.0.0...
3+
# Setup build
4+
Error: [Cabal-1071]
5+
Pre-build rules: can't find source for rule dependency:
6+
- Missing.hs
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import Test.Cabal.Prelude
2+
main = setupTest $ do
3+
setup "configure" []
4+
fails $ setup "build" []
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Main where
2+
3+
import Distribution.Simple ( defaultMainWithSetupHooks )
4+
import SetupHooks ( setupHooks )
5+
6+
main :: IO ()
7+
main = defaultMainWithSetupHooks setupHooks

0 commit comments

Comments
 (0)