{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} module Dhall.Test.DirectoryTree (tests) where import Control.Monad import Data.Either (partitionEithers) import Data.Either.Validation import Dhall.DirectoryTree import Lens.Family (set) import System.FilePath (()) import Test.Tasty import Test.Tasty.HUnit import qualified Data.Text.IO import qualified Dhall import qualified Dhall.Core import qualified System.Directory as Directory import qualified System.FilePath as FilePath import qualified System.PosixCompat.Files as Files tests :: TestTree tests = testGroup "to-directory-tree" [ testGroup "fixpointed" [ fixpointedType , fixpointedEmpty , fixpointedSimple #ifndef mingw32_HOST_OS , fixpointedPermissions , fixpointedUserGroup #endif ] ] fixpointedType :: TestTree fixpointedType = testCase "Type is as expected" $ do let file = "./tests/to-directory-tree/type.dhall" ref <- Dhall.inputExpr file expected' <- case directoryTreeType of Failure e -> assertFailure $ show e Success expr -> return expr assertBool "Type mismatch" $ expected' `Dhall.Core.judgmentallyEqual` ref fixpointedEmpty :: TestTree fixpointedEmpty = testCase "empty" $ do let outDir = "./tests/to-directory-tree/fixpoint-empty.out" path = "./tests/to-directory-tree/fixpoint-empty.dhall" entries <- runDirectoryTree False outDir path entries @?= [Directory outDir] fixpointedSimple :: TestTree fixpointedSimple = testCase "simple" $ do let outDir = "./tests/to-directory-tree/fixpoint-simple.out" path = "./tests/to-directory-tree/fixpoint-simple.dhall" entries <- runDirectoryTree False outDir path entries @?= [ Directory outDir , File $ outDir "file" , Directory $ outDir "directory" ] {- This test is disabled on Windows as it fails due to limitations of the : expected: 448 but got: 438 -} fixpointedPermissions :: TestTree fixpointedPermissions = testCase "permissions" $ do let outDir = "./tests/to-directory-tree/fixpoint-permissions.out" path = "./tests/to-directory-tree/fixpoint-permissions.dhall" entries <- runDirectoryTree False outDir path entries @?= [ Directory outDir , File $ outDir "file" ] s <- Files.getFileStatus $ outDir "file" let mode = Files.fileMode s `Files.intersectFileModes` Files.accessModes prettyFileMode mode @?= prettyFileMode Files.ownerModes fixpointedUserGroup :: TestTree fixpointedUserGroup = testCase "user and group" $ do let file = "./tests/to-directory-tree/fixpoint-usergroup.dhall" expr <- Dhall.inputExpr file entries <- decodeDirectoryTree expr entries @?= [ FileEntry $ Entry { entryName = "ids" , entryContent = "" , entryUser = Just (UserId 0) , entryGroup = Just (GroupId 0) , entryMode = Nothing } , FileEntry $ Entry { entryName = "names" , entryContent = "" , entryUser = Just (UserName "user") , entryGroup = Just (GroupName "group") , entryMode = Nothing } ] runDirectoryTree :: Bool -> FilePath -> FilePath -> IO [WalkEntry] runDirectoryTree allowSeparators outDir path = do doesOutDirExist <- Directory.doesDirectoryExist outDir when doesOutDirExist $ Directory.removeDirectoryRecursive outDir Directory.createDirectoryIfMissing True outDir text <- Data.Text.IO.readFile path let inputSettings = set Dhall.rootDirectory (FilePath.takeDirectory path) . set Dhall.sourceName path $ Dhall.defaultInputSettings expr <- Dhall.inputExprWithSettings inputSettings text toDirectoryTree allowSeparators outDir $ Dhall.Core.denote expr walkFsTree outDir data WalkEntry = Directory FilePath | File FilePath deriving (Eq, Show) walkFsTree :: FilePath -> IO [WalkEntry] walkFsTree dir = do entries <- Directory.listDirectory dir (ds, fs) <- fmap partitionEithers $ forM entries $ \path -> do let path' = dir path isDirectory <- Directory.doesDirectoryExist path' return $ if isDirectory then Left path' else Right (File path') entries' <- traverse walkFsTree ds return $ Directory dir : fs <> concat entries'