packages feed

stan-0.0.0.0: test/Test/Stan/Gen.hs

module Test.Stan.Gen
    ( Property
    , genFilePath
    , genId
    , genMediumList
    , genSmallList
    , genSmallString
    , genSmallText

      -- * Config
    , genConfig
    , genCheck
    , genCheckType
    , genCheckFilter
    , genScope
    , genSeverity
    , genCategory
    , genModuleName
    ) where

import Hedgehog (Gen, PropertyT)
import System.FilePath ((</>))

import Stan.Category (Category, stanCategories)
import Stan.Config (Check (..), CheckFilter (..), CheckType (..), Config, ConfigP (..), Scope (..))
import Stan.Core.Id (Id (..))
import Stan.Core.ModuleName (ModuleName (..))
import Stan.Inspection (Inspection)
import Stan.Inspection.All (inspectionsIds)
import Stan.Severity (Severity)

import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range


-- | Helper alias for tests.
type Property = PropertyT IO ()

-- | Generate an 'Int'.
genId :: Gen (Id a)
genId = Id <$> genSmallText

-- | Generate valid 'Inspection' 'Id's.
genInspectionId :: Gen (Id Inspection)
genInspectionId = Gen.element $ toList inspectionsIds

-- | Generate a small list of the given generated elements.
genSmallList :: Gen a -> Gen [a]
genSmallList = Gen.list (Range.linear 0 6)

-- | Generate a medium-size list
genMediumList :: Gen a -> Gen [a]
genMediumList = Gen.list (Range.linear 0 50)

genSmallText :: Gen Text
genSmallText = Gen.text (Range.linear 0 10) Gen.alphaNum

genSmallString :: Gen String
genSmallString = Gen.string (Range.linear 0 10) Gen.alphaNum

genConfig :: Gen Config
genConfig = ConfigP
    <$> genSmallList genCheck
    <*> genSmallList genScope
    <*> genSmallList genId

genCheck :: Gen Check
genCheck = Check
    <$> genCheckType
    <*> genCheckFilter
    <*> genScope

genCheckFilter :: Gen CheckFilter
genCheckFilter = Gen.choice
    [ CheckInspection  <$> genInspectionId
    , CheckSeverity    <$> genSeverity
    , CheckCategory    <$> genCategory
    , pure CheckAll
    ]

genScope :: Gen Scope
genScope = Gen.choice
    [ ScopeFile      <$> genFilePath
    , ScopeDirectory <$> genDirectory
    , pure ScopeAll
    ]

-- | Output one of the hardcoded directories
genDirectory :: Gen FilePath
genDirectory = Gen.element
    [ "src"
    , "app"
    , "lib/"
    , "test/"
    , "benchmark/"
    , "app/main/"
    , "src/app"
    , "src/lib/"
    , "src/lib/foo"
    , "src/lib/bar/"
    ]

-- | Generate a filepath either plain or from a predefined directory
genFilePath :: Gen FilePath
genFilePath = Gen.choice
    [ genSmallString
    , liftA2 (</>) genDirectory genSmallString
    ]

genCheckType :: Gen CheckType
genCheckType = Gen.enumBounded

genSeverity :: Gen Severity
genSeverity = Gen.enumBounded

genCategory :: Gen Category
genCategory = Gen.element stanCategories

genModuleName :: Gen ModuleName
genModuleName = ModuleName <$> genSmallText