Flexible tests for checkBuildPlan (#375)

@snoyberg Can you confirm that this simple test suite works for you?
I've set this up so that I can then add some cyclic dependencies and add
an occurs check for that, but figured I'd setup tests for some of the
existing invariants first.

Should be like:

    $ cabal test --ghc-options=-O0; cat dist/test/stackage-0.4.0-spec.log
    Building stackage-0.4.0...
    Preprocessing library stackage-0.4.0...
    In-place registering stackage-0.4.0...
    Preprocessing executable 'stackage' for stackage-0.4.0...
    Preprocessing test suite 'spec' for stackage-0.4.0...
    [3 of 4] Compiling Stackage.BuildPlanSpec ( test/Stackage/BuildPlanSpec.hs, dist/build/spec/spec-tmp/Stackage/BuildPlanSpec.o )
    Linking dist/build/spec/spec ...
    Running 1 test suites...
    Test suite spec: RUNNING...
    Test suite spec: PASS
    Test suite logged to: dist/test/stackage-0.4.0-spec.log
    1 of 1 test suites (1 of 1 test cases) passed.
    Test suite spec: RUNNING...

    Stackage.BuildPlan
      simple package set
      bad version range on depdendency fails
      nonexistent package fails to check
      default package set checks ok
    Stackage.CorePackages
      works
      contains known core packages
      getCoreExecutables includes known executables
    Stackage.PackageIndex
      works
      getLatestDescriptions gives reasonable results

    Finished in 14.3302 seconds
    9 examples, 0 failures
    Test suite spec: PASS
    Test suite logged to: dist/test/stackage-0.4.0-spec.log
This commit is contained in:
Chris Done 2015-01-04 22:26:33 +01:00
parent 5da6e5cfa4
commit 45b33ac54d
4 changed files with 131 additions and 15 deletions

View File

@ -10,6 +10,7 @@ module Stackage.BuildConstraints
, SystemInfo (..) , SystemInfo (..)
, getSystemInfo , getSystemInfo
, defaultBuildConstraints , defaultBuildConstraints
, toBC
) where ) where
import Control.Monad.Writer.Strict (execWriter, tell) import Control.Monad.Writer.Strict (execWriter, tell)

View File

@ -7,6 +7,7 @@
-- | Confirm that a build plan has a consistent set of dependencies. -- | Confirm that a build plan has a consistent set of dependencies.
module Stackage.CheckBuildPlan module Stackage.CheckBuildPlan
( checkBuildPlan ( checkBuildPlan
, BadBuildPlan
) where ) where
import Control.Monad.Writer.Strict (Writer, execWriter, tell) import Control.Monad.Writer.Strict (Writer, execWriter, tell)

View File

@ -1,22 +1,56 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings, NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings, NoImplicitPrelude #-}
module Stackage.BuildPlanSpec (spec) where module Stackage.BuildPlanSpec (spec) where
import Stackage.BuildPlan
import Stackage.Prelude
import Stackage.BuildConstraints
import Stackage.UpdateBuildPlan
import Test.Hspec
import qualified Data.Yaml as Y
import Distribution.Version (anyVersion)
import qualified Data.Map as Map import qualified Data.Map as Map
import Network.HTTP.Client (withManager) import qualified Data.Map.Strict as M
import Network.HTTP.Client.TLS (tlsManagerSettings) import qualified Data.Set as S
import Data.Yaml
import qualified Data.Yaml as Y
import Distribution.Version
import Network.HTTP.Client
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Stackage.BuildConstraints
import Stackage.BuildPlan
import Stackage.CheckBuildPlan
import Stackage.PackageDescription
import Stackage.Prelude
import Stackage.UpdateBuildPlan
import Test.Hspec
spec :: Spec spec :: Spec
spec = it "works" $ withManager tlsManagerSettings $ \man -> do spec = do
bc <- defaultBuildConstraints man it "simple package set" $ check testBuildConstraints $ makePackageSet
pkgs <- getLatestAllowedPlans bc [("foo", [0, 0, 0], [("bar", thisV [0, 0, 0])])
bp <- newBuildPlan pkgs bc ,("bar", [0, 0, 0], [])]
it "bad version range on depdendency fails" $ badBuildPlan $ makePackageSet
[("foo", [0, 0, 0], [("bar", thisV [1, 1, 0])])
,("bar", [0, 0, 0], [])]
it "nonexistent package fails to check" $ badBuildPlan $ makePackageSet
[("foo", [0, 0, 0], [("nonexistent", thisV [0, 0, 0])])
,("bar", [0, 0, 0], [])]
it "default package set checks ok" $ check defaultBuildConstraints getLatestAllowedPlans
-- | Checking should be considered a bad build plan.
badBuildPlan :: (BuildConstraints -> IO (Map PackageName PackagePlan))
-> void
-> IO ()
badBuildPlan m _ = do
mu <- try (check testBuildConstraints m)
case mu of
Left (_ :: BadBuildPlan) ->
return ()
Right () ->
error "Expected bad build plan."
-- | Check build plan with the given package set getter.
check :: (Manager -> IO BuildConstraints)
-> (BuildConstraints -> IO (Map PackageName PackagePlan))
-> IO ()
check readPlanFile getPlans = withManager tlsManagerSettings $ \man -> do
bc <- readPlanFile man
plans <- getPlans bc
bp <- newBuildPlan plans bc
let bs = Y.encode bp let bs = Y.encode bp
ebp' = Y.decodeEither bs ebp' = Y.decodeEither bs
@ -26,14 +60,74 @@ spec = it "works" $ withManager tlsManagerSettings $ \man -> do
forM_ allPackages $ \name -> forM_ allPackages $ \name ->
(name, lookup name (bpPackages bp')) `shouldBe` (name, lookup name (bpPackages bp')) `shouldBe`
(name, lookup name (bpPackages bp)) (name, lookup name (bpPackages bp))
bpGithubUsers bp' `shouldBe` bpGithubUsers bp bpGithubUsers bp' `shouldBe` bpGithubUsers bp
when (bp' /= bp) $ error "bp' /= bp" when (bp' /= bp) $ error "bp' /= bp"
bp2 <- updateBuildPlan pkgs bp bp2 <- updateBuildPlan plans bp
when (dropVersionRanges bp2 /= dropVersionRanges bp) $ error "bp2 /= bp" when (dropVersionRanges bp2 /= dropVersionRanges bp) $ error "bp2 /= bp"
checkBuildPlan bp
where where
dropVersionRanges bp = dropVersionRanges bp =
bp { bpPackages = map go $ bpPackages bp } bp { bpPackages = map go $ bpPackages bp }
where where
go pb = pb { ppConstraints = go' $ ppConstraints pb } go pb = pb { ppConstraints = go' $ ppConstraints pb }
go' pc = pc { pcVersionRange = anyVersion } go' pc = pc { pcVersionRange = anyVersion }
-- | Make a package set from a convenient data structure.
makePackageSet
:: [(String,[Int],[(String,VersionRange)])]
-> BuildConstraints
-> IO (Map PackageName PackagePlan)
makePackageSet ps _ =
return $
M.fromList $
map
(\(name,ver,deps) ->
( PackageName name
, dummyPackage ver $
M.fromList $
map
(\(dname,dver) ->
( PackageName dname
, DepInfo {diComponents = S.fromList
[CompLibrary]
,diRange = dver}))
deps))
ps
where
dummyPackage v deps =
PackagePlan
{ppVersion = Version v []
,ppGithubPings = mempty
,ppUsers = mempty
,ppConstraints =
PackageConstraints
{pcVersionRange = anyV
,pcMaintainer = Nothing
,pcTests = Don'tBuild
,pcHaddocks = Don'tBuild
,pcBuildBenchmarks = False
,pcFlagOverrides = mempty
,pcEnableLibProfile = False}
,ppDesc =
SimpleDesc
{sdPackages = deps
,sdTools = mempty
,sdProvidedExes = mempty
,sdModules = mempty}}
-- | This exact version is required.
thisV :: [Int] -> VersionRange
thisV ver = thisVersion (Version ver [])
-- | Accept any version.
anyV :: VersionRange
anyV = anyVersion
-- | Test plan.
testBuildConstraints :: void -> IO BuildConstraints
testBuildConstraints _ =
decodeFileEither
(fpToString fp) >>=
either throwIO toBC
where fp = "test/test-build-constraints.yaml"

View File

@ -0,0 +1,20 @@
packages:
"Test":
- foo
- bar
global-flags: []
skipped-tests: []
expected-test-failures: []
expected-haddock-failures: []
skipped-benchmarks: []
skipped-profiling: []
github-users:
bar:
- demo
package-flags:
foo:
demo: true