wasp/waspc/test/StrongPathTest.hs
2020-10-24 22:44:27 +02:00

292 lines
16 KiB
Haskell

module StrongPathTest where
import Test.Tasty.Hspec
import Data.Maybe (fromJust)
import qualified Path as P
import qualified Path.Posix as PP
import qualified Path.Windows as PW
import qualified System.FilePath as FP
import qualified System.FilePath.Posix as FPP
import qualified System.FilePath.Windows as FPW
import Fixtures (systemFpRoot, systemPathRoot)
import StrongPath
import StrongPath.Internal (RelPathPrefix (..),
extractRelPathPrefix,
relPathNumParentDirs)
import Test.Util (posixToSystemFp, posixToWindowsFp)
data Bar
data Fizz
-- TODO: I should look into using QuickCheck to simplify / enhcance StrongPath tests,
-- it would probably be a good fit for some cases.
spec_StrongPath :: Spec
spec_StrongPath = do
describe "Example with Foo file and Bar, Fizz and Kokolo dirs" $ do
let fooFileInBarDir = fromPathRelFile [P.relfile|foo.txt|] :: Path (Rel Bar) File
let barDirInFizzDir = fromPathRelDir [P.reldir|kokolo/bar|] :: Path (Rel Fizz) (Dir Bar)
let fizzDir = (fromPathAbsDir $ systemPathRoot P.</> [P.reldir|fizz|]) :: Path Abs (Dir Fizz)
let fooFile = (fizzDir </> barDirInFizzDir </> fooFileInBarDir) :: Path Abs File
let fooFileInFizzDir = (barDirInFizzDir </> fooFileInBarDir) :: Path (Rel Fizz) File
it "Paths are correctly concatenated" $ do
P.toFilePath (toPathAbsFile fooFile) `shouldBe` posixToSystemFp "/fizz/kokolo/bar/foo.txt"
P.toFilePath (toPathRelFile fooFileInFizzDir) `shouldBe` posixToSystemFp "kokolo/bar/foo.txt"
it "Paths are unchanged when packed from Path.Path and unpacked to Path.Path" $ do
let test pack unpack path = unpack (pack path) == path `shouldBe` True
test fromPathRelFile toPathRelFile [P.relfile|some/file.txt|]
test fromPathRelDir toPathRelDir [P.reldir|some/dir/|]
test fromPathAbsFile toPathAbsFile $ systemPathRoot P.</> [P.relfile|some/file.txt|]
test fromPathAbsDir toPathAbsDir $ systemPathRoot P.</> [P.reldir|some/file.txt|]
describe "relDirToPosix/relFileToPosix correctly converts relative strong path to Posix" $ do
describe "when strong path is relative dir" $ do
let expectedPosixPath = fromPathRelDirP [PP.reldir|test/dir/|]
it "from standard Win" $
fromJust (relDirToPosix $ fromPathRelDirW [PW.reldir|test\dir\|])
`shouldBe` expectedPosixPath
it "from standard Posix" $
fromJust (relDirToPosix $ fromPathRelDirP [PP.reldir|test/dir/|])
`shouldBe` expectedPosixPath
it "from standard System" $
fromJust (relDirToPosix $ fromPathRelDir [P.reldir|test/dir/|])
`shouldBe` expectedPosixPath
describe "correctly when strong path is relative file" $ do
let expectedPosixPath = fromPathRelFileP [PP.relfile|test/file|]
it "from standard Win" $
fromJust (relFileToPosix $ fromPathRelFileW [PW.relfile|test\file|])
`shouldBe` expectedPosixPath
it "from standard Posix" $
fromJust (relFileToPosix $ fromPathRelFileP [PP.relfile|test/file|])
`shouldBe` expectedPosixPath
it "from standard System" $
fromJust (relFileToPosix $ fromPathRelFile [P.relfile|test/file|])
`shouldBe` expectedPosixPath
describe "extractRelPathPrefix correctly extracts prefix from rel FilePath." $ do
it "when path starts with multiple ../" $ do
extractRelPathPrefix [FPP.pathSeparator] "../../" `shouldBe` (ParentDir 2, "")
extractRelPathPrefix [FPP.pathSeparator] "../.." `shouldBe` (ParentDir 2, "")
extractRelPathPrefix [FP.pathSeparator] ".." `shouldBe` (ParentDir 1, "")
extractRelPathPrefix [FP.pathSeparator, FPP.pathSeparator]"../../../a/b" `shouldBe` (ParentDir 3, "a/b")
extractRelPathPrefix [FPW.pathSeparator]"..\\a\\b" `shouldBe` (ParentDir 1, "a\\b")
it "when path does not start with ../" $ do
extractRelPathPrefix [FPP.pathSeparator] "a/b" `shouldBe` (NoPrefix, "a/b")
extractRelPathPrefix [FP.pathSeparator] "b" `shouldBe` (NoPrefix, "b")
extractRelPathPrefix [FP.pathSeparator] "." `shouldBe` (NoPrefix, ".")
describe "Parsing from FilePath" $ do
let runTest fpToParseIntoExpectedFp parser fpToParse =
let expectedFp = fpToParseIntoExpectedFp fpToParse
in it (fpToParse ++ " should parse into " ++ expectedFp) $ do
let sp = fromJust $ parser fpToParse
toFilePath sp `shouldBe` expectedFp
let runTestRel fpToParseIntoExpectedFp parser fpToParse expectedNumParentDirs =
let expectedFp = fpToParseIntoExpectedFp fpToParse
in it (fpToParse ++ " should parse into " ++ expectedFp) $ do
let sp = fromJust $ parser fpToParse
toFilePath sp `shouldBe` expectedFp
relPathNumParentDirs sp `shouldBe` expectedNumParentDirs
describe "into standard System" $ do
describe "into base Rel" $ do
describe "captures one or multiple ../ at start of relative path" $ do
let test = runTestRel id
test parseRelDir (posixToSystemFp "../../a/b/") 2
test parseRelDir (posixToSystemFp "../") 1
test parseRelDir (posixToSystemFp "../../") 2
test parseRelDir (posixToSystemFp "./") 0
test parseRelFile (posixToSystemFp "../a/b.txt") 1
describe "can parse from system FilePath" $ do
let test = runTestRel id
test parseRelDir (posixToSystemFp "../a/b/") 1
test parseRelDir (posixToSystemFp "a/b/") 0
test parseRelFile (posixToSystemFp "../a/b.txt") 1
test parseRelFile (posixToSystemFp "a/b.txt") 0
describe "can parse from posix FilePath" $ do
let test = runTestRel posixToSystemFp
test parseRelDir "../a/b/" 1
test parseRelDir "a/b/" 0
test parseRelFile "../a/b.txt" 1
test parseRelFile "a/b.txt" 0
describe "into base Abs" $ do
describe "can parse from system FilePath" $ do
let test = runTest id
test parseAbsDir (systemFpRoot FP.</> posixToSystemFp "a/b/")
test parseAbsFile (systemFpRoot FP.</> posixToSystemFp "a/b.txt")
describe "can parse from FilePath with system root and posix separators" $ do
let test = runTest posixToSystemFp
test parseAbsDir (systemFpRoot FP.</> "a/b/")
test parseAbsFile (systemFpRoot FP.</> "a/b.txt")
describe "into standard Windows" $ do
describe "into base Rel" $ do
describe "captures one or multiple ../ at start of relative path" $ do
let test = runTestRel posixToWindowsFp
test parseRelDirW (posixToSystemFp "../../a/b/") 2
test parseRelFileW (posixToSystemFp "../a/b.txt") 1
describe "can parse from windows FilePath" $ do
let test = runTestRel id
test parseRelDirW "..\\a\\b\\" 1
test parseRelDirW "a\\b\\" 0
test parseRelFileW "..\\a\\b.txt" 1
test parseRelFileW "..\\..\\a\\b.txt" 2
test parseRelFileW "a\\b.txt" 0
describe "can parse from posix FilePath" $ do
let test = runTestRel posixToWindowsFp
test parseRelDirW "../a/b/" 1
test parseRelDirW "a/b/" 0
test parseRelFileW "../a/b.txt" 1
test parseRelFileW "a/b.txt" 0
describe "into base Abs" $ do
describe "can parse from windows FilePath" $ do
let test = runTest id
test parseAbsDirW "C:\\a\\b\\"
test parseAbsFileW "C:\\a\\b.txt"
describe "can parse from FilePath with windows root and Posix separators" $ do
let test = runTest posixToWindowsFp
test parseAbsDirW "C:\\a/b/"
test parseAbsFileW "C:\\a/b.txt"
describe "into standard Posix" $ do
describe "into base Rel" $ do
describe "captures one or multiple ../ at start of relative path" $ do
let test = runTestRel id
test parseRelDirP "../../a/b/" 2
test parseRelFileP "../a/b.txt" 1
describe "can parse from posix FilePath" $ do
let test = runTestRel id
test parseRelDirP "../a/b/" 1
test parseRelDirP "a/b/" 0
test parseRelFileP "a/b.txt" 0
describe "into base Abs" $ do
describe "can parse from posix FilePath" $ do
let test = runTest id
test parseAbsDirP "/a/b/"
test parseAbsFileP "/a/b.txt"
describe "toFilePath correctly transforms strong path into FilePath" $ do
let test msp efp = it ("toFilePath (" ++ show msp ++ ") = " ++ efp) $
toFilePath (fromJust msp) `shouldBe` efp
test (parseRelDir $ posixToSystemFp "../") (posixToSystemFp "../")
test (parseRelDir $ posixToSystemFp "a/b") (posixToSystemFp "a/b/")
test (parseRelFile $ posixToSystemFp "../../foo.txt") (posixToSystemFp "../../foo.txt")
test (parseRelDirW "../") "..\\"
test (parseRelDirP "../") "../"
-- TODO: Add more tests.
describe "`parent` correctly returns parent dir" $ do
let test msp mexpectedSp =
it ("parent (" ++ show msp ++ ") == " ++ show mexpectedSp) $ do
let sp = fromJust msp
let expectedSp = fromJust mexpectedSp
parent sp `shouldBe` expectedSp
let tests relDirParser relFileParser absDirParser absFileParser root = do
test (relDirParser "a/b") (relDirParser "a")
test (relDirParser "../a") (relDirParser "..")
test (relDirParser "..") (relDirParser "../..")
test (relDirParser ".") (relDirParser "..")
test (relFileParser "a.txt") (relDirParser ".")
test (relFileParser "../a.txt") (relDirParser "..")
test (relFileParser "a/b.txt") (relDirParser "a")
test (absDirParser $ root ++ "a/b") (absDirParser $ root ++ "a")
test (absDirParser root) (absDirParser root)
test (absFileParser $ root ++ "a/b.txt") (absDirParser $ root ++ "a")
describe "when standard is System" $
tests parseRelDir parseRelFile parseAbsDir parseAbsFile systemFpRoot
describe "when standard is Windows" $
tests parseRelDirW parseRelFileW parseAbsDirW parseAbsFileW "C:\\"
describe "when standard is Posix" $
tests parseRelDirP parseRelFileP parseAbsDirP parseAbsFileP "/"
describe "</> correctly concatenates two corresponding paths" $ do
let test mlsp mrsp mexpectedSp =
it (show mlsp ++ " </> " ++ show mrsp ++ " == " ++ show mexpectedSp) $ do
let lsp = fromJust mlsp
let rsp = fromJust mrsp
let expectedSp = fromJust mexpectedSp
(lsp </> rsp) `shouldBe` expectedSp
let tests relDirParser relFileParser absDirParser absFileParser root = do
test (relDirParser "a/b") (relFileParser "c.txt") (relFileParser "a/b/c.txt")
test (relDirParser "a/b") (relFileParser "../c.txt") (relFileParser "a/c.txt")
test (relDirParser "..") (relFileParser "../c.txt") (relFileParser "../../c.txt")
test (relDirParser "..") (relDirParser "..") (relDirParser "../..")
test (relDirParser ".") (relDirParser "../a") (relDirParser "../a")
test (relDirParser ".") (relDirParser ".") (relDirParser ".")
test (relDirParser "a/b") (relDirParser "c/d") (relDirParser "a/b/c/d")
test (relDirParser "../a/b") (relDirParser "c/d") (relDirParser "../a/b/c/d")
test (absDirParser $ root ++ "a/b") (relFileParser "c.txt") (absFileParser $ root ++ "a/b/c.txt")
test (absDirParser $ root ++ "a/b") (relFileParser "../c.txt") (absFileParser $ root ++ "a/c.txt")
test (absDirParser $ root ++ "a") (relDirParser "../b") (absDirParser $ root ++ "b")
test (absDirParser $ root ++ "a/b") (relDirParser "../../../") (absDirParser root)
describe "when standard is System" $
tests parseRelDir parseRelFile parseAbsDir parseAbsFile systemFpRoot
describe "when standard is Windows" $
tests parseRelDirW parseRelFileW parseAbsDirW parseAbsFileW "C:\\"
describe "when standard is Posix" $
tests parseRelDirP parseRelFileP parseAbsDirP parseAbsFileP "/"
spec_Path :: Spec
spec_Path = do
-- Just checking that Path behaves in a way that we expect it to behave.
it "Path.Windows.parseRelDir correctly parses Windows path" $ do
fromJust (PW.parseRelDir ".\\") `shouldBe` fromJust (PW.parseRelDir "./")
fromJust (PW.parseRelDir "a\\\\b\\") `shouldBe` fromJust (PW.parseRelDir "a/b/")
fromJust (PW.parseRelDir "a\\b") `shouldBe` fromJust (PW.parseRelDir "a/b")
PW.toFilePath (fromJust $ PW.parseRelDir "a\\b\\") `shouldBe` "a\\b\\"
describe "Concatenation of System . paths works as expected" $ do
let test lp rp ep =
it (show lp ++ " </> " ++ show rp ++ " == " ++ show ep) $
(lp P.</> rp) `shouldBe` ep
test [P.reldir|.|] [P.reldir|.|] [P.reldir|.|]
test [P.reldir|a|] [P.reldir|.|] [P.reldir|a|]
test [P.reldir|.|] [P.reldir|a|] [P.reldir|a|]
test [P.reldir|.|] [P.relfile|c.txt|] [P.relfile|c.txt|]
-- NOTE: All of the failing Path tests are due to the badly implemented Include mechanism in Path.
-- I made a PR for fix on Path, so when that gets in we can uncomment these tests and also remove
-- workarounds in StrongPath / StrongPath.Internal.
-- describe "Concatenation of Win . paths works as expected" $ do
-- let test lp rp ep =
-- it (show lp ++ " </> " ++ show rp ++ " == " ++ show ep) $
-- (lp PW.</> rp) `shouldBe` ep
-- -- TODO: Fails on Linux/Mac: expected: ".\\" but got: ".\\.\\"
-- test [PW.reldir|.|] [PW.reldir|.|] [PW.reldir|.|]
-- -- TODO: Fails on Linux/Mac: expected: "a\\" but got: ".\\a\\"
-- test [PW.reldir|.|] [PW.reldir|a|] [PW.reldir|a|]
-- -- TODO: Fails on Linux/Mac: expected: "a\\" but got: "a\\.\\"
-- test [PW.reldir|a|] [PW.reldir|.|] [PW.reldir|a|]
-- describe "Concatenation of Posix . paths works as expected" $ do
-- let test lp rp ep =
-- it (show lp ++ " </> " ++ show rp ++ " == " ++ show ep) $
-- (lp PP.</> rp) `shouldBe` ep
-- -- TODO: Fails on Win: expected: "./" but got: "././"
-- test [PP.reldir|.|] [PP.reldir|.|] [PP.reldir|.|]
-- -- TODO: Fails on Win: expected: "a/" but got: "./a/"
-- test [PP.reldir|.|] [PP.reldir|a|] [PP.reldir|a|]
-- -- TODO: Fails on Win: expected: "a/" but got: "a/./"
-- test [PP.reldir|a|] [PP.reldir|.|] [PP.reldir|a|]
describe "Parsing rel path with .. at start should fail" $ do
let test parser p =
it (show p ++ " should successfully parse") $
parser p `shouldBe` Nothing
describe "for PW.parseRelDir" $ do
test PW.parseRelDir "../a"
-- -- TODO: This fails on Linux/Mac! Weird, I thought Path does not allow relative paths starting with ..?
-- -- expected: Nothing but got: Just "..\\a\\"
-- test PW.parseRelDir "..\\a"
describe "for P.parseRelDir" $ do
test P.parseRelDir "../a"
test P.parseRelDir $ ".." FP.</> "a"
describe "for PP.parseRelDir" $ do
test PP.parseRelDir "../a"