hix-0.2.0.0: test/Hix/Test/GhciTest.hs
module Hix.Test.GhciTest where
import Control.Monad.Trans.Class (lift)
import Exon (exon)
import Hedgehog (TestT, evalEither, (===))
import Path (Abs, Dir, File, Path, Rel, SomeBase (Rel), absdir, absfile, reldir, relfile, (</>))
import Path.IO (getCurrentDir, withSystemTempDir)
import Hix.Data.Error (pathText)
import Hix.Data.GhciConfig (
ComponentConfig (..),
ComponentName,
EnvConfig (EnvConfig),
EnvRunner (EnvRunner),
GhciConfig (..),
PackageConfig (..),
PackagesConfig,
SourceDir (SourceDir),
SourceDirs (SourceDirs),
)
import qualified Hix.Data.GhciTest as GhciTest
import Hix.Env (envRunner)
import Hix.Ghci (assemble, ghcidCmdlineFromOptions)
import Hix.Monad (runM)
import qualified Hix.Options as Options
import Hix.Options (
ComponentCoords (ComponentCoords),
ComponentSpec (ComponentSpec),
EnvRunnerOptions (EnvRunnerOptions),
GhciOptions (GhciOptions, component),
PackageSpec (PackageSpec),
TargetSpec (TargetForComponent, TargetForFile),
TestOptions (TestOptions),
)
root :: Path Abs Dir
root =
[absdir|/project|]
runner1 :: EnvRunner
runner1 =
EnvRunner [absfile|/runner1.bash|]
runner2 :: EnvRunner
runner2 =
EnvRunner [absfile|/runner2.bash|]
defaultRunner :: EnvRunner
defaultRunner =
EnvRunner [absfile|/default|]
component :: ComponentName -> Path Rel Dir -> EnvRunner -> ComponentConfig
component name dir runner =
ComponentConfig {
name,
sourceDirs = SourceDirs [SourceDir dir],
runner = Just runner,
extensions = [],
language = "GHC2021",
ghcOptions = [],
prelude = Nothing
}
packages :: PackagesConfig
packages =
[
("api", PackageConfig {
name = "api",
src = [reldir|packages/api|],
components = [
("library", component "api" [reldir|lib|] runner1),
("server", component "server" [reldir|app|] runner1),
("api-test", component "api-test" [reldir|test|] runner1)
]
}),
("core", PackageConfig {
name = "core",
src = [reldir|packages/core|],
components = [
("library", component "core" [reldir|lib|] runner1),
("core-test", component "core-test" [reldir|test|] runner2)
]
})
]
spec1 :: TargetSpec
spec1 =
TargetForComponent ComponentCoords {
package = PackageSpec "api" (Just (Rel [reldir|api|])),
component = ComponentSpec "test" (Just (SourceDir [reldir|test|]))
}
options :: GhciOptions
options =
GhciOptions {
config = Left GhciConfig {
packages,
setup = [("generic", "import Test.Tasty")],
run = [("generic", ("check . property . test"))],
args = ["-Werror"]
},
component = spec1,
test = TestOptions {
mod = "Api.ServerTest",
test = Just "test_server",
runner = Just "generic"
}
}
ghcidTarget ::
Path Abs Dir ->
Path Abs File ->
Text
ghcidTarget cwd scriptFile =
[exon|ghcid --command="ghci -Werror -i#{path} -ghci-script=#{pathText scriptFile}" --test='#{test}'|]
where
test = "(check . property . test) test_server"
path = [exon|#{dir}packages/api/test/:#{dir}packages/api/lib/:#{dir}packages/core/lib/|]
dir = pathText cwd
test_ghcid :: TestT IO ()
test_ghcid = do
cwd <- getCurrentDir
res <- lift $ withSystemTempDir "hix-test" \ tmp ->
runM root (ghcidCmdlineFromOptions tmp options)
cmdline <- evalEither res
ghcidTarget cwd cmdline.ghci.scriptFile === cmdline.cmdline
spec2 :: TargetSpec
spec2 =
TargetForFile (root </> [relfile|packages/core/test/Main.hs|])
spec3 :: TargetSpec
spec3 =
TargetForComponent ComponentCoords {
package = PackageSpec "packages/core" (Just (Rel [reldir|packages/core|])),
component = ComponentSpec "core-test" (Just (SourceDir [reldir|core-test|]))
}
runnerFor :: EnvRunner -> TargetSpec -> TestT IO ()
runnerFor target spec = do
res <- evalEither =<< liftIO (runM root (envRunner conf))
target === res
where
conf = EnvRunnerOptions (Left (EnvConfig packages defaultRunner)) (Just spec)
test_componentEnv :: TestT IO ()
test_componentEnv = do
runnerFor runner1 spec1
runnerFor runner2 spec2
runnerFor runner2 spec3
spec4 :: TargetSpec
spec4 =
TargetForFile (root </> [relfile|packages/core/test/Core/Test/Main.hs|])
target_moduleName :: Text
target_moduleName =
[exon|import Test.Tasty
:load #{m}
import #{m}|]
where
m = "Core.Test.Main"
test_moduleName :: TestT IO ()
test_moduleName = do
conf <- evalEither =<< liftIO (runM root (assemble options { component = spec4 }))
target_moduleName === conf.script