dojang-0.1.0: test/Dojang/Types/ContextSpec.hs
{-# LANGUAGE DisambiguateRecordFields #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
module Dojang.Types.ContextSpec (spec) where
import Data.List (isInfixOf, sort, sortOn)
import System.IO.Error
( ioeGetErrorString
, ioeGetErrorType
, ioeGetFileName
, ioeGetLocation
)
import Prelude hiding (readFile, writeFile)
import Data.ByteString qualified (length)
import Data.Map.Strict (Map, fromList)
import System.FilePath (combine)
import System.OsPath (OsPath, encodeFS, (</>))
import Test.Hspec (Spec, describe, it, runIO, specify)
import Test.Hspec.Expectations.Pretty (shouldBe, shouldReturn, shouldThrow)
import Dojang.MonadFileSystem (MonadFileSystem (..))
import Dojang.MonadFileSystem qualified (FileType (..))
import Dojang.Syntax.Manifest.Writer (writeManifestFile)
import Dojang.TestUtils (Entry (..), makeFixtureTree, withTempDir)
import Dojang.Types.Context
( Context (..)
, FileCorrespondence (..)
, FileDeltaKind (..)
, FileEntry (..)
, FileStat (..)
, RouteState (..)
, getRouteState
, listFiles
, makeCorrespond
, makeCorrespondBetweenThreeDirs
, makeCorrespondBetweenThreeFiles
, makeCorrespondBetweenTwoDirs
, makeCorrespondWithDestination
, routePaths
)
import Dojang.Types.Environment
( Architecture (..)
, Environment (..)
, Kernel (..)
, OperatingSystem (..)
)
import Dojang.Types.EnvironmentPredicate.Evaluate (EvaluationWarning (..))
import Dojang.Types.FilePathExpression (FilePathExpression (..), (+/+))
import Dojang.Types.FileRouteSpec (monikerMap)
import Dojang.Types.Manifest (manifest)
import Dojang.Types.MonikerName (MonikerName, parseMonikerName)
import Dojang.Types.Repository
( Repository (..)
, RouteMapWarning (..)
, RouteResult (..)
)
import GHC.IO.Exception (IOErrorType (InappropriateType))
spec :: Spec
spec = do
src <- runIO $ encodeFS "src"
inter <- runIO $ encodeFS "inter"
dst <- runIO $ encodeFS "dst"
foo <- runIO $ encodeFS "foo"
bar <- runIO $ encodeFS "bar"
baz <- runIO $ encodeFS "baz"
qux <- runIO $ encodeFS "qux"
-- cSpell:ignore quux corge
quux <- runIO $ encodeFS "quux"
corge <- runIO $ encodeFS "corge"
intermediateDir <- runIO $ encodeFS ".dojang"
manifestFilename' <- runIO $ encodeFS "dojang.toml"
let Right posix = parseMonikerName "posix"
let Right undefined' = parseMonikerName "undefined"
let Right windows = parseMonikerName "windows"
let fileRoutes =
[
( baz
,
[
( undefined'
, Just $ Root Nothing +/+ BareComponent "__dojang_test_baz__"
)
, (windows, Just $ Substitution "BAZ")
]
)
]
:: Map OsPath [(MonikerName, Maybe FilePathExpression)]
let dirRoutes =
[ (foo, [(posix, Just $ Substitution "FOO"), (windows, Nothing)])
,
( bar
,
[ (posix, Just $ Substitution "BAR")
, (windows, Just $ Root $ Just 'B')
]
)
]
:: Map OsPath [(MonikerName, Maybe FilePathExpression)]
let manifest' =
Dojang.Types.Manifest.manifest
monikerMap
fileRoutes
dirRoutes
[(foo, ["ignore-*"])]
let repositoryFixture repoPath = do
-- The tree of the repository fixture looks like this:
-- .
-- ├── bar/
-- │ └── foo
-- ├── baz
-- ├── dojang.toml
-- └── foo/
-- ├── bar/
-- │ └── foo
-- ├── baz/
-- └── foo
-- Total 4 directories and 5 files
writeManifestFile manifest' $ repoPath </> manifestFilename'
createDirectory $ repoPath </> foo
writeFile (repoPath </> foo </> foo) "asdf"
createDirectory $ repoPath </> foo </> bar
writeFile (repoPath </> foo </> bar </> foo) "asdf asdf"
createDirectory $ repoPath </> foo </> baz
createDirectory $ repoPath </> bar
writeFile (repoPath </> bar </> foo) "foobar"
writeFile (repoPath </> baz) "foo bar baz"
let repo =
Repository
repoPath
(repoPath </> intermediateDir)
manifest'
return repo
let withContextFixture action = withTempDir $ \tmpDir _ -> do
createDirectory $ tmpDir </> src
createDirectory $ tmpDir </> foo
repo <- repositoryFixture $ tmpDir </> src
let ctx = Context
repo
(Environment Linux X86_64 $ Kernel "Linux" "5.10.0-8")
$ \e ->
return $ case e of
"FOO" -> Just $ tmpDir </> foo
"BAR" -> Just $ tmpDir </> bar
"BAZ" -> Just $ tmpDir </> baz
_ -> Nothing
action ctx tmpDir
specify "routePaths" $ withContextFixture $ \ctx tmpDir -> do
(results, ws) <- routePaths ctx
ws `shouldBe` [EnvironmentPredicateWarning $ UndefinedMoniker undefined']
sortOn (.sourcePath) results
`shouldBe` [ RouteResult
{ sourcePath = tmpDir </> src </> bar
, routeName = bar
, destinationPath = tmpDir </> bar
, fileType = Dojang.MonadFileSystem.Directory
}
, RouteResult
{ sourcePath = tmpDir </> src </> foo
, routeName = foo
, destinationPath = tmpDir </> foo
, fileType = Dojang.MonadFileSystem.Directory
}
]
specify "makeCorrespondWithDestination"
$ withContextFixture
$ \ctx tmpDir -> do
(correspond, ws) <-
makeCorrespondWithDestination ctx (tmpDir </> bar </> foo)
ws `shouldBe` [EnvironmentPredicateWarning $ UndefinedMoniker undefined']
correspond
`shouldBe` Just
( FileCorrespondence
{ source =
FileEntry
(tmpDir </> src </> bar </> foo)
(File 6)
, sourceDelta = Added
, intermediate =
FileEntry
(tmpDir </> src </> intermediateDir </> bar </> foo)
Missing
, destination = FileEntry (tmpDir </> bar </> foo) Missing
, destinationDelta = Unchanged
}
)
let ctx' = ctx{environment = ctx.environment{operatingSystem = Windows}}
(correspond', ws') <-
makeCorrespondWithDestination ctx' (tmpDir </> baz)
ws' `shouldBe` [EnvironmentPredicateWarning $ UndefinedMoniker undefined']
correspond'
`shouldBe` Just
( FileCorrespondence
{ source = FileEntry (tmpDir </> src </> baz) (File 11)
, sourceDelta = Added
, intermediate =
FileEntry (tmpDir </> src </> intermediateDir </> baz) Missing
, destination = FileEntry (tmpDir </> baz) Missing
, destinationDelta = Unchanged
}
)
(correspond'', ws'') <-
makeCorrespondWithDestination ctx (tmpDir </> corge)
correspond'' `shouldBe` Nothing
ws'' `shouldBe` ws
specify "makeCorrespond" $ withContextFixture $ \ctx tmpDir -> do
(corresponds, ws) <- makeCorrespond ctx
ws `shouldBe` [EnvironmentPredicateWarning $ UndefinedMoniker undefined']
sortOn (.source.path) corresponds
`shouldBe` [ FileCorrespondence
{ source =
FileEntry
(tmpDir </> src </> bar </> foo)
(File 6)
, sourceDelta = Added
, intermediate =
FileEntry
(tmpDir </> src </> intermediateDir </> bar </> foo)
Missing
, destination = FileEntry (tmpDir </> bar </> foo) Missing
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source =
FileEntry
(tmpDir </> src </> foo </> bar)
Directory
, sourceDelta = Added
, intermediate =
FileEntry
(tmpDir </> src </> intermediateDir </> foo </> bar)
Missing
, destination = FileEntry (tmpDir </> foo </> bar) Missing
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source =
FileEntry
(tmpDir </> src </> foo </> bar </> foo)
(File 9)
, sourceDelta = Added
, intermediate =
FileEntry
( tmpDir
</> src
</> intermediateDir
</> foo
</> bar
</> foo
)
Missing
, destination =
FileEntry (tmpDir </> foo </> bar </> foo) Missing
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source =
FileEntry (tmpDir </> src </> foo </> baz) Directory
, sourceDelta = Added
, intermediate =
FileEntry
(tmpDir </> src </> intermediateDir </> foo </> baz)
Missing
, destination = FileEntry (tmpDir </> foo </> baz) Missing
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source =
FileEntry (tmpDir </> src </> foo </> foo) (File 4)
, sourceDelta = Added
, intermediate =
FileEntry
(tmpDir </> src </> intermediateDir </> foo </> foo)
Missing
, destination = FileEntry (tmpDir </> foo </> foo) Missing
, destinationDelta = Unchanged
}
]
describe "listFiles" $ do
it "lists files recursively" $ withTempDir $ \tmpDir _ -> do
_ <- repositoryFixture tmpDir
files <- listFiles tmpDir []
manifestData <- readFile $ tmpDir </> manifestFilename'
let manifestSize = toEnum $ Data.ByteString.length manifestData
sort files
`shouldBe` [ FileEntry bar Directory
, FileEntry (bar </> foo) $ File 6
, FileEntry baz $ File 11
, FileEntry manifestFilename' $ File manifestSize
, FileEntry foo Directory
, FileEntry (foo </> bar) Directory
, FileEntry (foo </> bar </> foo) $ File 9
, FileEntry (foo </> baz) Directory
, FileEntry (foo </> foo) $ File 4
]
it "filters out files by ignorePatterns" $ withTempDir $ \tmpDir _ -> do
_ <- repositoryFixture tmpDir
files <- listFiles tmpDir ["foo/b*"]
manifestData <- readFile $ tmpDir </> manifestFilename'
let manifestSize = toEnum $ Data.ByteString.length manifestData
sort files
`shouldBe` [ FileEntry bar Directory
, FileEntry (bar </> foo) $ File 6
, FileEntry baz $ File 11
, FileEntry manifestFilename' $ File manifestSize
, FileEntry foo Directory
, FileEntry (foo </> foo) $ File 4
]
it "only accepts a directory path" $ withTempDir $ \tmpDir tmpDir' -> do
() <- writeFile (tmpDir </> foo) "foo"
listFiles (tmpDir </> foo) [] `shouldThrow` \e ->
(ioeGetErrorType e == InappropriateType)
&& (ioeGetLocation e == "listFiles")
&& (ioeGetFileName e == Just (tmpDir' `combine` "foo"))
&& ("not a directory" `isInfixOf` show e)
specify "makeCorrespondBetweenThreeFiles" $ withTempDir $ \tmpDir _ -> do
let makeCorrespond_ =
makeCorrespondBetweenThreeFiles
(tmpDir </> inter)
(tmpDir </> src)
(tmpDir </> dst)
writeFile (tmpDir </> inter) "unchanged"
writeFile (tmpDir </> src) "unchanged"
writeFile (tmpDir </> dst) "unchanged"
makeCorrespond_
`shouldReturn` FileCorrespondence
{ source = FileEntry (tmpDir </> src) $ File 9
, sourceDelta = Unchanged
, intermediate = FileEntry (tmpDir </> inter) $ File 9
, destination = FileEntry (tmpDir </> dst) $ File 9
, destinationDelta = Unchanged
}
writeFile (tmpDir </> src) "modified!"
writeFile (tmpDir </> dst) "modified"
makeCorrespond_
`shouldReturn` FileCorrespondence
{ source = FileEntry (tmpDir </> src) $ File 9
, sourceDelta = Modified
, intermediate = FileEntry (tmpDir </> inter) $ File 9
, destination = FileEntry (tmpDir </> dst) $ File 8
, destinationDelta = Modified
}
removeFile (tmpDir </> inter)
writeFile (tmpDir </> src) "added"
writeFile (tmpDir </> dst) "added"
makeCorrespond_
`shouldReturn` FileCorrespondence
{ source = FileEntry (tmpDir </> src) $ File 5
, sourceDelta = Added
, intermediate = FileEntry (tmpDir </> inter) Missing
, destination = FileEntry (tmpDir </> dst) $ File 5
, destinationDelta = Added
}
writeFile (tmpDir </> inter) "removed"
removeFile (tmpDir </> src)
removeFile (tmpDir </> dst)
makeCorrespond_
`shouldReturn` FileCorrespondence
{ source = FileEntry (tmpDir </> src) Missing
, sourceDelta = Removed
, intermediate = FileEntry (tmpDir </> inter) $ File 7
, destination = FileEntry (tmpDir </> dst) Missing
, destinationDelta = Removed
}
writeFile (tmpDir </> inter) "dir is disallowed"
createDirectory (tmpDir </> src)
filename <- decodePath $ tmpDir </> src
makeCorrespond_ `shouldThrow` \e ->
( ioeGetErrorString e
== "makeCorrespondBetweenThreeFiles: "
++ "expected a file, but got a directory"
)
&& (ioeGetFileName e == Just filename)
specify "makeCorrespondBetweenThreeDirs" $ withTempDir $ \tmpDir _ -> do
() <-
makeFixtureTree
(tmpDir </> foo)
[ (inter, D [])
, (src, D [])
, (dst, D [])
]
emptyCorresponds <-
makeCorrespondBetweenThreeDirs
(tmpDir </> foo </> inter)
(tmpDir </> foo </> src)
(tmpDir </> foo </> dst)
[]
sortOn (.source.path) emptyCorresponds `shouldBe` []
unchanged <- encodePath "unchanged"
added <- encodePath "added"
removed <- encodePath "removed"
modified <- encodePath "modified"
ignored <- encodePath "ignored"
() <-
makeFixtureTree
(tmpDir </> bar)
[
( inter
, D
[ (unchanged, D [(foo, F "foo-unchanged")])
, (added, D [])
,
( removed
, D
[ (foo, F "foo-src-removed")
, (bar, F "bar-dst-removed")
, (baz, F "baz-both-removed")
, (qux, D [])
]
)
,
( modified
, D
[ (foo, F "foo")
, (bar, F "bar")
, (baz, F "baz")
, (qux, F "qux-file-to-dir")
, (quux, D [])
, (corge, F "same-size-but-different-content")
]
)
,
( ignored
, D
[ (foo, F "foo-ignored-but-tracked")
, (baz, F "baz-ignored-but-indexed")
]
)
]
)
,
( src
, D
[ (unchanged, D [(foo, F "foo-unchanged")])
,
( added
, D
[ (foo, F "foo-src-added")
, (baz, F "baz-both-added")
, (qux, D [])
]
)
, (removed, D [(bar, F "bar-dst-removed")])
,
( modified
, D
[ (foo, F "foo-src-modified")
, (bar, F "bar")
, (baz, F "baz-src-modified")
, (qux, D [])
, (quux, F "qux-dir-to-file")
, (corge, F "same-length-but--different-body")
]
)
,
( ignored
, D
[ (foo, F "foo-ignored-but-tracked")
, (bar, F "bar-ignored-but-added")
]
)
]
)
,
( dst
, D
[ (unchanged, D [(foo, F "foo-unchanged")])
,
( added
, D
[ (bar, F "bar-dst-added")
, (baz, F "baz-both-added")
, (qux, D [])
]
)
, (removed, D [(foo, F "foo-src-removed")])
,
( modified
, D
[ (foo, F "foo")
, (bar, F "bar-dst-modified")
, (baz, F "baz-dst-modified")
, (qux, F "qux-file-to-dir")
, (quux, D [])
, (corge, F "equivalent-length-but-different")
]
)
,
( ignored
, D
[ (foo, F "foo-ignored-but-tracked")
, (bar, F "bar-ignored-but-added")
, (baz, F "baz-ignored-but-indexed")
]
)
]
)
]
corresponds <-
makeCorrespondBetweenThreeDirs
(tmpDir </> bar </> inter)
(tmpDir </> bar </> src)
(tmpDir </> bar </> dst)
["ignored"]
sortOn (.source.path) corresponds
`shouldBe` [ FileCorrespondence
{ source = FileEntry added Directory
, sourceDelta = Unchanged
, intermediate = FileEntry added Directory
, destination = FileEntry added Directory
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (added </> bar) Missing
, sourceDelta = Unchanged
, intermediate = FileEntry (added </> bar) Missing
, destination = FileEntry (added </> bar) (File 13)
, destinationDelta = Added
}
, FileCorrespondence
{ source = FileEntry (added </> baz) (File 14)
, sourceDelta = Added
, intermediate = FileEntry (added </> baz) Missing
, destination = FileEntry (added </> baz) (File 14)
, destinationDelta = Added
}
, FileCorrespondence
{ source = FileEntry (added </> foo) (File 13)
, sourceDelta = Added
, intermediate = FileEntry (added </> foo) Missing
, destination = FileEntry (added </> foo) Missing
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (added </> qux) Directory
, sourceDelta = Added
, intermediate = FileEntry (added </> qux) Missing
, destination = FileEntry (added </> qux) Directory
, destinationDelta = Added
}
, FileCorrespondence
{ source = FileEntry ignored Directory
, sourceDelta = Unchanged
, intermediate = FileEntry ignored Directory
, destination = FileEntry ignored Directory
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (ignored </> bar) (File 21)
, sourceDelta = Added
, intermediate = FileEntry (ignored </> bar) Missing
, destination = FileEntry (ignored </> bar) (File 21)
, destinationDelta = Added
}
, FileCorrespondence
{ source = FileEntry (ignored </> baz) Missing
, sourceDelta = Removed
, intermediate = FileEntry (ignored </> baz) (File 23)
, destination = FileEntry (ignored </> baz) (File 23)
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (ignored </> foo) (File 23)
, sourceDelta = Unchanged
, intermediate = FileEntry (ignored </> foo) (File 23)
, destination = FileEntry (ignored </> foo) (File 23)
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry modified Directory
, sourceDelta = Unchanged
, intermediate = FileEntry modified Directory
, destination = FileEntry modified Directory
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (modified </> bar) (File 3)
, sourceDelta = Unchanged
, intermediate = FileEntry (modified </> bar) (File 3)
, destination = FileEntry (modified </> bar) (File 16)
, destinationDelta = Modified
}
, FileCorrespondence
{ source = FileEntry (modified </> baz) (File 16)
, sourceDelta = Modified
, intermediate = FileEntry (modified </> baz) (File 3)
, destination = FileEntry (modified </> baz) (File 16)
, destinationDelta = Modified
}
, FileCorrespondence
{ source = FileEntry (modified </> corge) (File 31)
, sourceDelta = Modified
, intermediate = FileEntry (modified </> corge) (File 31)
, destination = FileEntry (modified </> corge) (File 31)
, destinationDelta = Modified
}
, FileCorrespondence
{ source = FileEntry (modified </> foo) (File 16)
, sourceDelta = Modified
, intermediate = FileEntry (modified </> foo) (File 3)
, destination = FileEntry (modified </> foo) (File 3)
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (modified </> quux) (File 15)
, sourceDelta = Modified
, intermediate = FileEntry (modified </> quux) Directory
, destination = FileEntry (modified </> quux) Directory
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (modified </> qux) Directory
, sourceDelta = Modified
, intermediate = FileEntry (modified </> qux) (File 15)
, destination = FileEntry (modified </> qux) (File 15)
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry removed Directory
, sourceDelta = Unchanged
, intermediate = FileEntry removed Directory
, destination = FileEntry removed Directory
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (removed </> bar) (File 15)
, sourceDelta = Unchanged
, intermediate = FileEntry (removed </> bar) (File 15)
, destination = FileEntry (removed </> bar) Missing
, destinationDelta = Removed
}
, FileCorrespondence
{ source = FileEntry (removed </> baz) Missing
, sourceDelta = Removed
, intermediate = FileEntry (removed </> baz) (File 16)
, destination = FileEntry (removed </> baz) Missing
, destinationDelta = Removed
}
, FileCorrespondence
{ source = FileEntry (removed </> foo) Missing
, sourceDelta = Removed
, intermediate = FileEntry (removed </> foo) (File 15)
, destination = FileEntry (removed </> foo) (File 15)
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (removed </> qux) Missing
, sourceDelta = Removed
, intermediate = FileEntry (removed </> qux) Directory
, destination = FileEntry (removed </> qux) Missing
, destinationDelta = Removed
}
, FileCorrespondence
{ source = FileEntry unchanged Directory
, sourceDelta = Unchanged
, intermediate = FileEntry unchanged Directory
, destination = FileEntry unchanged Directory
, destinationDelta = Unchanged
}
, FileCorrespondence
{ source = FileEntry (unchanged </> foo) (File 13)
, sourceDelta = Unchanged
, intermediate = FileEntry (unchanged </> foo) (File 13)
, destination = FileEntry (unchanged </> foo) (File 13)
, destinationDelta = Unchanged
}
]
specify "makeCorrespondBetweenTwoDirs" $ withTempDir $ \tmpDir _ -> do
() <-
makeFixtureTree
(tmpDir </> foo)
[ (foo, F "foo")
,
( bar
, D
[ (foo, F "bar/foo")
, (bar, F "bar/bar")
, (baz, D [])
]
)
, (baz, F "baz")
,
( qux
, D
[ (foo, F "qux/foo")
, (quux, F "qux/quux")
]
)
]
() <-
makeFixtureTree
(tmpDir </> bar)
[ (foo, F "foo 2")
,
( bar
, D
[ (foo, F "bar/foo")
, (baz, D [(bar, F "bar/baz/bar")])
]
)
, (baz, F "baz")
,
( qux
, D
[ (foo, F "qux/foo")
, (quux, F "qux/quux 2")
]
)
]
makeCorrespondBetweenTwoDirs (tmpDir </> foo) (tmpDir </> bar) []
`shouldReturn` fromList
[ (foo, (FileEntry foo $ File 3, FileEntry foo $ File 5))
, (bar, (FileEntry bar Directory, FileEntry bar Directory))
,
( bar </> foo
, (FileEntry (bar </> foo) $ File 7, FileEntry (bar </> foo) $ File 7)
)
,
( bar </> bar
, (FileEntry (bar </> bar) $ File 7, FileEntry (bar </> bar) Missing)
)
,
( bar </> baz
,
( FileEntry (bar </> baz) Directory
, FileEntry (bar </> baz) Directory
)
)
,
( bar </> baz </> bar
,
( FileEntry (bar </> baz </> bar) Missing
, FileEntry (bar </> baz </> bar) $ File 11
)
)
, (baz, (FileEntry baz $ File 3, FileEntry baz $ File 3))
,
( qux
, (FileEntry qux Directory, FileEntry qux Directory)
)
,
( qux </> foo
, (FileEntry (qux </> foo) $ File 7, FileEntry (qux </> foo) $ File 7)
)
,
( qux </> quux
,
( FileEntry (qux </> quux) $ File 8
, FileEntry (qux </> quux) $ File 10
)
)
]
makeCorrespondBetweenTwoDirs
(tmpDir </> baz) -- This dir does not exist
(tmpDir </> bar)
[]
`shouldReturn` fromList
[ (foo, (FileEntry foo Missing, FileEntry foo $ File 5))
, (bar, (FileEntry bar Missing, FileEntry bar Directory))
,
( bar </> foo
,
( FileEntry (bar </> foo) Missing
, FileEntry (bar </> foo) $ File 7
)
)
,
( bar </> baz
,
( FileEntry (bar </> baz) Missing
, FileEntry (bar </> baz) Directory
)
)
,
( bar </> baz </> bar
,
( FileEntry (bar </> baz </> bar) Missing
, FileEntry (bar </> baz </> bar) $ File 11
)
)
, (baz, (FileEntry baz Missing, FileEntry baz $ File 3))
, (qux, (FileEntry qux Missing, FileEntry qux Directory))
,
( qux </> foo
, (FileEntry (qux </> foo) Missing, FileEntry (qux </> foo) $ File 7)
)
,
( qux </> quux
,
( FileEntry (qux </> quux) Missing
, FileEntry (qux </> quux) $ File 10
)
)
]
specify "getRouteState" $ withContextFixture $ \ctx tmpDir -> do
(state, ws) <- getRouteState ctx (tmpDir </> src)
ws `shouldBe` [EnvironmentPredicateWarning $ UndefinedMoniker undefined']
state `shouldBe` NotRouted
(state', ws') <- getRouteState ctx (tmpDir </> foo </> foo)
ws' `shouldBe` ws
state' `shouldBe` Routed foo
ignoreMe <- encodePath "ignore-me"
(state'', ws'') <- getRouteState ctx (tmpDir </> foo </> ignoreMe)
ws'' `shouldBe` ws
state'' `shouldBe` Ignored foo "ignore-*"
let ctx' = ctx{environment = ctx.environment{operatingSystem = FreeBSD}}
(stateOnNullRouting, ws''') <- getRouteState ctx' (tmpDir </> src)
ws''' `shouldBe` ws
stateOnNullRouting `shouldBe` NotRouted