stan-0.0.0.0: test/Test/Stan/Config.hs
module Test.Stan.Config
( configSpec
) where
import Hedgehog (forAll, (===))
import Test.Hspec (Spec, describe, it, parallel, shouldBe)
import Test.Hspec.Hedgehog (hedgehog)
import Stan.Config (Check (..), CheckFilter (..), CheckType (..), Config, ConfigP (..), Scope (..),
applyChecks, applyChecksFor, applyConfig, mkDefaultChecks)
import Stan.Core.Id (Id (..))
import Stan.Inspection (Inspection)
import Test.Stan.Gen (Property, genCheck, genFilePath, genMediumList, genSmallList)
import qualified Data.HashMap.Strict as HM
import qualified Data.HashSet as HS
configSpec :: Spec
configSpec = describe "Stan Configuration Tests"
applyChecksSpec
applyChecksSpec :: Spec
applyChecksSpec = describe "Configuration checks aggregation" $ do
applyChecksUnitSpec
applyChecksPropertySpec
applyConfigSpec
applyChecksUnitSpec :: Spec
applyChecksUnitSpec = describe "applyCheck: Unit Tests" $ do
it "All inspections when empty Check list" $
applyChecks files [] `shouldBe` defMap
it "Including all inspections" $
applyChecks files [Check Include CheckAll ScopeAll] `shouldBe` defMap
it "All inspections are excluded" $
applyChecks files [Check Exclude CheckAll ScopeAll]
`shouldBe` (mempty <$ defMap)
it "Excluding single Inspection ID works" $ do
let iId = Id "STAN-0001"
applyChecks
files
[Check Exclude (CheckInspection iId) ScopeAll]
`shouldBe`
(HS.delete iId <$> defMap)
it "Excluding single file works" $
applyChecks
files
[Check Exclude CheckAll (ScopeFile "baz.hs")]
`shouldBe`
HM.adjust (const mempty) "baz.hs" defMap
it "Excluding a directory works" $
applyChecks
files
[Check Exclude CheckAll (ScopeDirectory "src/")]
`shouldBe`
HM.adjust (const mempty) "src/foo.hs"
( HM.adjust (const mempty) "src/bar.hs" defMap)
it "Excluding inspection in a single file" $ do
let iId = Id "STAN-0001"
applyChecks
files
[Check
Exclude
(CheckInspection iId)
(ScopeFile "baz.hs")
]
`shouldBe`
HM.adjust (HS.delete iId) "baz.hs" defMap
applyChecksPropertySpec :: Spec
applyChecksPropertySpec = describe "applyCheck: Property Tests" $ parallel $ do
it "Idempotence: applyChecks . applyChecks ≡ applyChecks"
idempotenceProperty
it "CheckType Inversion: include c . exclude c ≡ id"
inversionProperty
idempotenceProperty :: Property
idempotenceProperty = hedgehog $ do
paths <- forAll $ genSmallList genFilePath
checks <- forAll $ genMediumList genCheck
let filesMap = mkDefaultChecks paths
applyChecksFor (applyChecksFor filesMap checks) checks === applyChecksFor filesMap checks
inversionProperty :: Property
inversionProperty = hedgehog $ do
paths <- forAll $ genSmallList genFilePath
excludeCheck <- forAll $ genCheck <&> \c -> c { checkType = Exclude }
let includeCheck = excludeCheck { checkType = Include }
let filesMap = mkDefaultChecks paths
applyChecksFor (applyChecksFor filesMap [excludeCheck]) [includeCheck] === filesMap
applyConfigSpec :: Spec
applyConfigSpec = describe "applyConfig tests" $ do
it "'applyConfig' with no removed files is the same as 'applyChecks'" $ do
let checks = [Check Exclude CheckAll ScopeAll]
applyConfig files (emptyConfig{ configChecks = checks })
`shouldBe` applyChecks files checks
it "Removes all files" $
applyConfig files removeAllConfig `shouldBe` mempty
it "Removes a single file" $
applyConfig files removeFileConfig
`shouldBe` HM.delete "baz.hs" defMap
it "Removes all files from a directory" $
applyConfig files removeDirectoryConfig
`shouldBe` HM.delete "src/foo.hs" (HM.delete "src/bar.hs" defMap)
it "Removes 2 files" $
applyConfig files removeTwoFilesConfig
`shouldBe` HM.delete "src/foo.hs" (HM.delete "baz.hs" defMap)
it "Removes all files when they are specified explicitly" $
applyConfig files removeAllExplicitConfig `shouldBe` mempty
where
emptyConfig :: Config
emptyConfig = ConfigP
{ configChecks = []
, configRemoved = []
, configIgnored = []
}
removeAllConfig :: Config
removeAllConfig = emptyConfig { configRemoved = [ScopeAll] }
removeFileConfig :: Config
removeFileConfig = emptyConfig { configRemoved = [ScopeFile "baz.hs"] }
removeDirectoryConfig :: Config
removeDirectoryConfig = emptyConfig { configRemoved = [ScopeDirectory "src/"] }
removeTwoFilesConfig :: Config
removeTwoFilesConfig = emptyConfig
{ configRemoved = [ScopeFile "baz.hs", ScopeFile "src/foo.hs"]
}
removeAllExplicitConfig :: Config
removeAllExplicitConfig = emptyConfig
{ configRemoved = [ScopeFile "baz.hs", ScopeDirectory "src"]
}
files :: [FilePath]
files = ["src/foo.hs", "src/bar.hs", "baz.hs"]
defMap :: HashMap FilePath (HashSet (Id Inspection))
defMap = mkDefaultChecks files